$Id: Testing.lhs,v 1.4 1998/02/22 18:11:21 leavens Exp $

> module Testing where

The type constructor TestCase is a representation of tests in Haskell.
To make a TestCase, you write, for example:
     Test "1 + 2" (1 + 2) 3 (==)
     Test "choose s" (choose s) s elem
That is, the first argument is some identifying string,
the second is the Haskell code for the test,
the third is data that gives the expected result(s) of the test,
and the fourth is a function that compares the result to what was expected.
    
> data (Show code, Show expected) => TestCase code expected =
>       Test String code expected (code -> expected -> Bool)

The following is convenient for making test cases that use equality.

> eqTest :: (Show a, Eq a) => String -> a -> a -> TestCase a a
> eqTest id code expected = Test id code expected (==)

For running a single test case, use the following.
The number returned is the number of test cases that failed.
For example, you can write
  run_test (Test "1 + 2" (1 + 2) 3 (==))
    >>= (\i -> putStrLn ((show i) ++ " errors"))
and this will run the test.

> run_test :: (Show a, Show b) => TestCase a b -> IO Integer
> run_test (Test id code expected comp) =
>   do putStrLn id
>      putStr arrow
>      putStrLn (show code)
>      if comp code expected
>       then return 0
>       else do putStr wrong
>               putStrLn (show expected)
>               return 1
>    where arrow = "        ==> "
>          wrong = "  EXPECTED: "

The following will run an entire list of tests.
For example, you can write
   run_tests [Test "1 + 2" (1 + 2) 3 (==),
              eqTest "1 + 2" (1 + 2) 4
             ]

> run_tests :: (Show a, Show b) => [TestCase a b] -> IO ()
> run_tests ts = 
>   do errs <- run_test_list 0 ts
>      if errs == 0
>       then do putStrLn "All tests passed!"
>       else do putStrLn ("TOTAL UNEXPECTED RESULTS THIS TEST RUN: "
>                         ++ show errs)

> run_test_list :: (Show a, Show b) => Integer -> [TestCase a b] -> IO Integer
> run_test_list errs_so_far [] =
>   do return errs_so_far
> run_test_list errs_so_far (t:ts) =
>   do err_count <- run_test t
>      run_test_list (errs_so_far + err_count) ts
