I needed some quick unit testing for a library, to rule out a run-time error. In the end, it wasn’t that complicated, but the “straightforward” way of implmenting unit testing with haskell/cabal isn’t as straightforward as it could be.
I ended up implementing this guy’s solution (stackoverflow.com, 8 years ago):
… which is a combination of
test-framework, HUnit, test-framework-hunit
with cabal Test Suite exitcode-stdio-1.0.
It does exactly what I needed, only the following things felt a bit awkard:
What is this alternative cabal test suite detailed-0.9? Documentation is slim. When should I use one over the other?
Those three libraries are fine, I guess, but given the basic nature of the task: Why isn’t it just one thing? I tried working with HUnit alone, BUT exitcode-stdio-1.0 requires working with exit codes that I have to put in place manually … thus I prefer the defaultMain from test-framework.
I certainly don’t mean to complain. Maybe there is a more straightforward way of implementing unit testing that I overlooked.
If, however, this is how it’s done, I hope this posts contributes to the documentation of the topic.
It borrows from rspec and seems for sure a better experience than what suggested in that stackoverflow answer. If hspec if fit for your purposes, I suggest giving it a go!
I believe exitcode-stdio is the standard way to test and the other ways are not really used anymore.
I didn’t run into issues with using HUnit directly with this code:
module Main where
import Test.HUnit
foo :: Int -> (Int, Int)
foo 3 = (1, 2)
foo _ = (0, 0)
partA :: Int -> IO (Int, Int)
partA _ = pure (5, 2) -- change to (5,3) if you want the tests to succeed
partB :: Int -> IO Bool
partB x = pure (x == 3)
test1, test2 :: Test
test1 = TestCase $ assertEqual "for (foo 3)," (1, 2) (foo 3)
test2 = TestCase $ do
(x, y) <- partA 3
assertEqual "for the first result of partA," 5 x
b <- partB y
assertBool ("(partB " ++ show y ++ ") failed") b
main :: IO ()
main = runTestTTAndExit (TestList [TestLabel "test1" test1, TestLabel "test2" test2])