Skip to content

Commit

Permalink
feat: support for skipped tests - xdescribe xit xprop (#67)
Browse files Browse the repository at this point in the history
Fixes #64.
  • Loading branch information
mrcjkb authored Mar 12, 2023
1 parent 8913078 commit 072f6fe
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 50 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.5.0] - 2023-03-12
### Added
- Health checks (`:help checkhealth`).
- Hspec: Support for skipped tests (`xdescribe` `xit`, `xprop`).

## [0.4.0] - 2023-03-10
### Added
Expand Down
31 changes: 13 additions & 18 deletions lua/neotest-haskell/hspec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ local describe_query = [[
(_ (_ (exp_apply
(exp_name (variable) @func_name)
(exp_literal) @namespace.name
) (#eq? @func_name "describe"))) @namespace.definition
) (#any-of? @func_name "describe" "xdescribe"))) @namespace.definition
;; describe (qualified)
(_ (_ (exp_apply
(exp_name (qualified_variable (variable) @func_name))
(exp_literal) @namespace.name
) (#eq? @func_name "describe"))) @namespace.definition
) (#any-of? @func_name "describe" "xdescribe"))) @namespace.definition
]]

---Parse the positions in a test file.
Expand All @@ -24,29 +24,17 @@ local describe_query = [[
function hspec.parse_positions(path)
local tests_query = describe_query
.. [[
;; it (unqualified)
;; unqualified
((exp_apply
(exp_name (variable) @func_name)
(exp_literal) @test.name
) (#eq? @func_name "it")) @test.definition
) (#any-of? @func_name "it" "xit" "prop" "xprop")) @test.definition
;; it (qualified)
;; qualified
((exp_apply
(exp_name (qualified_variable (variable) @func_name))
(exp_literal) @test.name
) (#eq? @func_name "it")) @test.definition
;; prop (unqualified)
((exp_apply
(exp_name (variable) @func_name)
(exp_literal) @test.name
) (#eq? @func_name "prop")) @test.definition
;; prop (qualified)
((exp_apply
(exp_name (qualified_variable (variable) @func_name))
(exp_literal) @test.name
) (#eq? @func_name "prop")) @test.definition
) (#any-of? @func_name "it" "xit" "prop" "xprop")) @test.definition
]]
return util.parse_positions(path, tests_query)
end
Expand Down Expand Up @@ -243,13 +231,17 @@ function hspec.parse_results(context, out_path, tree)
local lines = vim.split(data, '\n')
local failure_positions = {}
local success_positions = {}
local skipped_positions = {}
for _, line in ipairs(lines) do
local failed = line:match('%s*(.*)%s.✘')
local succeeded = line:match('%s*(.*)%s.✔')
local skipped = line:match('%s*(.*)%s%[‐%]')
if failed then
failure_positions[#failure_positions + 1] = failed
elseif succeeded then
success_positions[#success_positions + 1] = succeeded
elseif skipped then
skipped_positions[#skipped_positions + 1] = skipped
end
end

Expand All @@ -261,6 +253,9 @@ function hspec.parse_results(context, out_path, tree)
for _, test_name in ipairs(success_positions) do
set_test_status(test_name, 'passed')
end
for _, test_name in ipairs(skipped_positions) do
set_test_status(test_name, 'skipped')
end
for _, test_name in ipairs(failure_positions) do
local errors = get_hspec_errors(lines, test_name)
set_test_status(test_name, 'failed', errors)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ spec = describe "oneOf successful tests" $ do
it "returns two of the thing" $
oneOf (3 :: Integer) `shouldBe` [3, 3]

xit "skipped it" pending

xprop "skipped prop" pending

xdescribe "skipped describe" $
it "implicitly skipped it" pending
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ spec = H.describe "twoOf successful tests" $ do
H.describe "twoOf failing tests" $
H.it "returns one of the thing" $
twoOf (3 :: Integer) `H.shouldBe` [3]

H.xit "skipped it" H.pending

Q.xprop "skipped prop" H.pending

H.xdescribe "skipped describe" $
H.it "implicitly skipped it" H.pending
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ spec = spec1 >> spec2

spec1 :: Spec
spec1 = describe "Prelude.head" $ do
it "Returns the first element of a list" $ head [23 ..] `shouldBe` (23 :: Int)
xit "Returns the first element of a list" $ head [23 ..] `shouldBe` (23 :: Int)

prop "Returns the first element of an arbitrary list" $ \x xs ->
head (x : xs) `shouldBe` (5 :: Int)
Expand Down
3 changes: 2 additions & 1 deletion tests/fixtures/results/test_file_fail.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ Running 1 test suites...
Test suite subpackage1-spec: RUNNING...

Prelude.head
Returns the first element of a list [✔]
Returns the first element of a list [‐]
# PENDING: No reason given
Returns the first element of an arbitrary list [✘]
Empty list
Throws on empty list [✔]
Expand Down
52 changes: 22 additions & 30 deletions tests/hspec_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,11 @@ describe('hspec', function()
assert_has_position(result, filename_pos_id)
local ns_1_pos_id = filename_pos_id .. '::"section 1"'
assert_has_position(result, ns_1_pos_id)
local test_1_1_pos_id = ns_1_pos_id .. '::"is a tautology"'
assert_has_position(result, test_1_1_pos_id)
local test_1_2_pos_id = ns_1_pos_id .. '::"assumes that 2 is 1"'
assert_has_position(result, test_1_2_pos_id)
assert_has_position(result, ns_1_pos_id .. '::"is a tautology"')
assert_has_position(result, ns_1_pos_id .. '::"assumes that 2 is 1"')
local ns_2_pos_id = filename_pos_id .. '::"section 2"'
assert_has_position(result, ns_2_pos_id)
local test_2_1_pos_id = ns_2_pos_id .. '::"only contains one test"'
assert_has_position(result, test_2_1_pos_id)
assert_has_position(result, ns_2_pos_id .. '::"only contains one test"')
end)
end)
async.it('unqualified imports 1', function()
Expand All @@ -53,14 +50,15 @@ describe('hspec', function()
assert_has_position(result, filename_pos_id)
local ns_1_pos_id = filename_pos_id .. '::"oneOf successful tests"'
assert_has_position(result, ns_1_pos_id)
local test_1_1_pos_id = ns_1_pos_id .. '::"returns one of the thing"'
assert_has_position(result, test_1_1_pos_id)
local test_1_2_pos_id = ns_1_pos_id .. '::"always has length 1"'
assert_has_position(result, test_1_2_pos_id)
assert_has_position(result, ns_1_pos_id .. '::"returns one of the thing"')
assert_has_position(result, ns_1_pos_id .. '::"always has length 1"')
local ns_2_pos_id = ns_1_pos_id .. '::"oneOf failing tests"'
assert_has_position(result, ns_2_pos_id)
local test_2_1_pos_id = ns_2_pos_id .. '::"returns two of the thing"'
assert_has_position(result, test_2_1_pos_id)
assert_has_position(result, ns_2_pos_id .. '::"returns two of the thing"')
assert_has_position(result, ns_1_pos_id .. '::"skipped it"')
assert_has_position(result, ns_1_pos_id .. '::"skipped prop"')
local ns_3_pos_id = ns_1_pos_id .. '::"skipped describe"'
assert_has_position(result, ns_3_pos_id .. '::"implicitly skipped it"')
end)
async.it('unqualified imports 2', function()
local test_file = Path:new(test_cwd .. '/fixtures/hspec/stack/multi-package/subpackage1/test/Fix1/FixtureSpec.hs')
Expand All @@ -70,20 +68,16 @@ describe('hspec', function()
assert_has_position(result, filename_pos_id)
local ns_1_pos_id = filename_pos_id .. '::"Prelude.head"'
assert_has_position(result, ns_1_pos_id)
local test_1_1_pos_id = ns_1_pos_id .. '::"Returns the first element of a list"'
assert_has_position(result, test_1_1_pos_id)
local test_1_2_pos_id = ns_1_pos_id .. '::"Returns the first element of an arbitrary list"'
assert_has_position(result, test_1_2_pos_id)
assert_has_position(result, ns_1_pos_id .. '::"Returns the first element of a list"')
assert_has_position(result, ns_1_pos_id .. '::"Returns the first element of an arbitrary list"')
local ns_2_pos_id = ns_1_pos_id .. '::"Empty list"'
assert_has_position(result, ns_2_pos_id)
local test_2_1_pos_id = ns_2_pos_id .. '::"Throws on empty list"'
assert_has_position(result, test_2_1_pos_id)
assert_has_position(result, ns_2_pos_id .. '::"Throws on empty list"')
local ns_3_pos_id = filename_pos_id .. '::"Prelude.tail"'
assert_has_position(result, ns_3_pos_id)
local ns_4_pos_id = ns_3_pos_id .. '::"Single element list"'
assert_has_position(result, ns_4_pos_id)
local test_4_1_pos_id = ns_4_pos_id .. '::"Returns the empty list"'
assert_has_position(result, test_4_1_pos_id)
assert_has_position(result, ns_4_pos_id .. '::"Returns the empty list"')
end)
async.it('qualified imports', function()
local test_file = Path:new(test_cwd .. '/fixtures/hspec/cabal/multi-package/subpackage2/test/Fix2/FixtureSpec.hs')
Expand All @@ -93,14 +87,15 @@ describe('hspec', function()
assert_has_position(result, filename_pos_id)
local ns_1_pos_id = filename_pos_id .. '::"twoOf successful tests"'
assert_has_position(result, ns_1_pos_id)
local test_1_1_pos_id = ns_1_pos_id .. '::"returns two of the thing"'
assert_has_position(result, test_1_1_pos_id)
local test_1_2_pos_id = ns_1_pos_id .. '::"always has length 2"'
assert_has_position(result, test_1_2_pos_id)
assert_has_position(result, ns_1_pos_id .. '::"returns two of the thing"')
assert_has_position(result, ns_1_pos_id .. '::"always has length 2"')
local ns_2_pos_id = ns_1_pos_id .. '::"twoOf failing tests"'
assert_has_position(result, ns_2_pos_id)
local test_2_1_pos_id = ns_2_pos_id .. '::"returns one of the thing"'
assert_has_position(result, test_2_1_pos_id)
assert_has_position(result, ns_2_pos_id .. '::"returns one of the thing"')
assert_has_position(result, ns_1_pos_id .. '::"skipped it"')
assert_has_position(result, ns_1_pos_id .. '::"skipped prop"')
local ns_3_pos_id = ns_1_pos_id .. '::"skipped describe"'
assert_has_position(result, ns_3_pos_id .. '::"implicitly skipped it"')
end)

describe('parse results', function()
Expand Down Expand Up @@ -135,10 +130,7 @@ describe('hspec', function()
status = 'passed',
}, results[filename .. '::"Prelude.head"::"Empty list"::"Throws on empty list"'])
assert.same({
status = 'passed',
}, results[filename .. '::"Prelude.head"::"Returns the first element of a list"'])
assert.same({
status = 'passed',
status = 'skipped',
}, results[filename .. '::"Prelude.head"::"Returns the first element of a list"'])
assert.same(failure, results[filename .. '::"Prelude.head"::"Returns the first element of an arbitrary list"'])
assert.same({
Expand Down

0 comments on commit 072f6fe

Please sign in to comment.