I'm trying to come up with a unit testing framework for Haskell that is
- small and self-contained
- produces TAP-compatible output
- exits abnormally on failure (instead of relying on the TAP consumer to validate all the output).
- has a simple API with easy to understand compile-time errors. (That's the motivation for committing to concrete types in the interface).
With that in mind, this is what I came up with:
I'm mainly looking for things that
- are not idiomatic Haskell
- would hamper usability in very small to small projects in The Real World.
module TestTrivial ( tests ) where import System.Exit (exitSuccess, exitFailure) testsImpl :: [(Bool, String)] -> Int -> Bool -> IO () testsImpl  nextTest status = putStrLn ("1.." ++ show (nextTest - 1)) <> doExit where doExit = if status then exitSuccess else exitFailure testsImpl ((cond, msg):xs) nextTest success = putStrLn msg' <> rest where ok = if cond then "ok" else "not ok" num = show nextTest f  = unwords [ok, num] f m = unwords [ok, num, "-", msg] msg' = f msg rest = testsImpl xs (nextTest + 1) (success && cond) tests :: [(Bool, String)] -> IO () tests xs = testsImpl xs 1 True
And here's an example test suite using this library.
module TestAdd where import TestTrivial main = tests [ (1 + 4 == 5, "1 + 4 == 5") , (5 + 6 /= 7, "5 + 6 /= 7") ]
And what it produces. ... Despite the
- sign separating the test number from the message and how strange that looks here, the output is formatted correctly.
ok 1 - 1 + 4 == 5 ok 2 - 5 + 6 /= 7 1..2