运行 尽管存在测试失败,但“cabal 测试”通过了

Running “cabal test” passes although there are test failures

我有一个 Cabal 测试目标:

test-suite Tests
  type:              exitcode-stdio-1.0
  main-is:           Main.hs
  hs-source-dirs:    test, src
  build-depends:     base, …
  default-language:  Haskell2010

还有一个简单的测试Main.hs:

import Test.HUnit
testSanity = TestCase $ assertEqual "Should fail" 2 1
main = runTestTT testSanity

现在运行cabal test通过:

Test suite Tests: RUNNING...
Test suite Tests: PASS
Test suite logged to: dist/test/Project-0.1.0-Tests.log
1 of 1 test suites (1 of 1 test cases) passed.

即使在测试套件日志中正确记录了失败:

Test suite Tests: RUNNING...

Cases: 1  Tried: 0  Errors: 0  Failures: 0

### Failure:
Should fail
expected: 2
 but got: 1
Cases: 1  Tried: 1  Errors: 0  Failures: 1
Test suite Tests: PASS
Test suite logged to: dist/test/Project-0.1.0-Tests.log

我做错了什么?

main 必须是 IO a 类型,其中 a 可以是任何东西,并且该值与 POSIX 退出状态没有任何关系程序。您需要查看 runTest 返回的 Counts 并明确选择成功或失败的输出代码。

import System.Exit

main :: IO ()
main = do
    cs@(Counts _ _ errs fails) <- runTestTT testSanity
    putStrLn (showCounts cs)
    if (errs > 0 || fails > 0) 
        then exitFailure
        else exitSuccess

我相信 exitcode-stdio-1.0 希望测试通过程序的退出代码来传达失败。但是,如果您从 shell 手动 运行 测试程序(查看 dist/build 目录),我想您会发现退出代码始终为 0。

这是一个相关的 SO 问题,它建议如果您的套件未通过,您的测试应该调用 exitFailure

QuickCheck exit status on failures, and cabal integration

FWIW,使用 stack:

时可以正常工作
$ mkdir new-dir
$ cd new-dir
$ stack new
(edit new-template.cabal to add HUnit as a test dependency)
(add test case to test/Spec.hs)
$ stack test

也许stack也在扫描测试输出。