Just to walk the walk, and not just talk the talk, here's a quick unit testing 'diff' driver I hacked up for QuickCheck.
When run, it 'diffs' (well, just prints ;-) the incorrect values from the unit test: $ runhaskell T.hs sort unit test : Falsifiable after 0 tests: - [1,2,3] + [1,3,2] >From a normal QC specification like: prop0 = (sort [3,2,1], [1,3,2]) main = mapM_ (\(s,a) -> printf "%-25s: " s >> a n) tests where n = 100 tests = [("sort unit test", mytest prop0)] The full driver code is attached. It is just proof of concept, but you can see how to extend it to be smarter/prettier. Note that we actually probably want to use SmallCheck here, to prevent bogus repetition of the test. (I.e. 500 tests all passed, for a unit test). Note also, the driver would need further extending, since we've changed the structure of the Testable values. Cheers, Don
import Data.List import Text.Printf import System.IO import System.Random import Test.QuickCheck prop0 = (sort [3,2,1], [1,3,2]) main = mapM_ (\(s,a) -> printf "%-25s: " s >> a n) tests where n = 100 tests = [("sort unit test", mytest prop0)] ------------------------------------------------------------------------ -- And a custom driver that `diff's the output mytest :: (Show a, Eq a) => (a,a) -> Int -> IO () mytest (a,b) n = mycheck defaultConfig { configMaxTest=n , configEvery= \n args -> [] } a b mycheck :: (Show a , Eq a) => Config -> a -> a -> IO () mycheck config a b = do rnd <- newStdGen mytests config (evaluate (a == b)) a b rnd 0 0 [] mytests :: (Show a , Eq a) => Config -> Gen Result -> a -> a -> StdGen -> Int -> Int -> [[String]] -> IO () mytests config gen a b rnd0 ntest nfail stamps | ntest == configMaxTest config = do done "OK," ntest stamps | nfail == configMaxFail config = do done "Arguments exhausted after" ntest stamps | otherwise = do putStr (configEvery config ntest (arguments result)) >> hFlush stdout case ok result of Nothing -> mytests config gen a b rnd1 ntest (nfail+1) stamps Just True -> mytests config gen a b rnd1 (ntest+1) nfail (stamp result:stamps) Just False -> putStr ( "Falsifiable after " ++ show ntest ++ " tests:\n" ++ "- " ++ show a ++ "\n" ++ "+ " ++ show b ++ "\n" ) >> hFlush stdout where result = generate (configSize config ntest) rnd2 gen (rnd1,rnd2) = split rnd0 done :: String -> Int -> [[String]] -> IO () done mesg ntest stamps = do putStr ( mesg ++ " " ++ show ntest ++ " tests" ++ table ) where table = display . map entry . reverse . sort . map pairLength . group . sort . filter (not . null) $ stamps display [] = ".\n" display [x] = " (" ++ x ++ ").\n" display xs = ".\n" ++ unlines (map (++ ".") xs) pairLength xss@(xs:_) = (length xss, xs) entry (n, xs) = percentage n ntest ++ " " ++ concat (intersperse ", " xs) percentage n m = show ((100 * n) `div` m) ++ "%"
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe