-- pa3_test.hs -- Glenn G. Chappell -- Version 2 -- 5 Mar 2009 -- -- For CS 331 Spring 2009 -- Test Program for Assignment 3 Functions & Variables -- Used in Assignment 3, Exercise A module Main where import PA3 -- For Assignment 3 Functions & Variables ------------------------------------------------------------------------ -- Testing Package ------------------------------------------------------------------------ -- TestState a -- Data type for holding results of tests -- First item in pair is a Maybe giving pass/fail results so far: -- Just _ means all passed so far -- Nothing means at least one failure so far -- Second item in pair is IO for output of tests data TestState a = TS (Maybe a, IO a) -- Accessor functions for parts of a TestState value -- For convenience tsMaybe (TS (x, y)) = x tsIO (TS (x, y)) = y -- Make TestState a monad in the obvious way instance Monad TestState where return a = TS (return a, return a) TS (x, y) >>= f = TS (x >>= f1, y >>= f2) where f1 = tsMaybe . f f2 = tsIO . f -- testMsg -- Print a message (e.g., "Test Suite: ...") in TestState monad testMsg :: String -> TestState () testMsg str = TS (Just (), putStrLn str) -- test -- Do test in TestState monad -- Given result of test (Bool: True if passed) & description of test -- Adds result of test & description + pass/fail output to monadic value test :: Bool -> String -> TestState () test success descrip = TS (theMaybe, putStrLn fullDescrip) where theMaybe | success = Just () | otherwise = Nothing fullDescrip = " Test: " ++ descrip ++ " - " ++ passFailStr passFailStr | success = "passed" | otherwise = "********** FAILED **********" -- testEq -- Like test, but given 2 values, checks whether they are equal testEq :: Eq a => a -> a -> String -> TestState () testEq a b str = test (a == b) str -- printResults -- Converts TestState monadic value to IO monadic value -- with summary of all test results printResults :: TestState () -> IO () printResults z = do -- Do IO from tests tsIO z putStrLn "" -- Then output summary: all passed or not if tsMaybe z == Nothing then putStrLn "Tests ********** UNSUCCESSFUL **********" else putStrLn "All tests successful" ------------------------------------------------------------------------ -- Test Suites ------------------------------------------------------------------------ -- test_evens -- Test Suite for function evens test_evens = do testMsg "Test Suite: Function evens" testEq (evens [5,2,4,7,3,5]) [5,4,3] "evens, Medium-sized list #1" testEq (evens [5,2,4,7,3,5,0]) [5,4,3,0] "evens, Medium-size list #2" testEq (evens [1..500]) [1,3..500] "evens, Large list" testEq (evens [5]) [5] "evens, Singleton list" testEq (evens "Howdy, there!") "Hwy hr!" "evens, String" testEq (evens "") "" "evens, Empty list" -- test_max2 -- Test Suite for function max2 test_max2 = do testMsg "Test Suite: Function max2" testEq (max2 [5,2,4,7,3,1]) [5,7] "max2, Medium-sized list #1" testEq (max2 [7,2,4,7,3,5]) [7,7] "max2, Medium-sized list #2" testEq (max2 [1..500]) [499,500] "max2, Large list" testEq (max2 [5]) [5] "max2, Singleton list" testEq (max2 "Howdy, there!") "wy" "max2, String" testEq (max2 "") "" "max2, Empty list" -- test_almostMax -- Test Suite for function almostMax test_almostMax = do testMsg "Test Suite: Function almostMax" testEq (almostMax [5,2,4,7,3,1]) [5] "almostMax, Medium-sized list #1" testEq (almostMax [7,2,4,7,3,5]) [7] "almostMax, Medium-sized list #2" testEq (almostMax [1..500]) [499] "almostMax, Large list" testEq (almostMax [5]) [] "almostMax, Singleton list" testEq (almostMax "Howdy, there!") "w" "almostMax, String" testEq (almostMax "") "" "almostMax, Empty list" -- test_primes -- Test Suite for variable primes test_primes = do testMsg "Test Suite: Variable primes [NOTE: MAY BE SLOW]" testEq (take 200 primes) primes200 "primes, first 200 values" testEq (primes !! 300) 1993 "primes, value @ index 300" where -- primes200: first 200 primes primes200 = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61, 67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139, 149,151,157,163,167,173,179,181,191,193,197,199,211,223,227, 229,233,239,241,251,257,263,269,271,277,281,283,293,307,311, 313,317,331,337,347,349,353,359,367,373,379,383,389,397,401, 409,419,421,431,433,439,443,449,457,461,463,467,479,487,491, 499,503,509,521,523,541,547,557,563,569,571,577,587,593,599, 601,607,613,617,619,631,641,643,647,653,659,661,673,677,683, 691,701,709,719,727,733,739,743,751,757,761,769,773,787,797, 809,811,821,823,827,829,839,853,857,859,863,877,881,883,887, 907,911,919,929,937,941,947,953,967,971,977,983,991,997, 1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069, 1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163, 1171,1181,1187,1193,1201,1213,1217,1223] -- allTests -- Run all test suites for Assignment 3 functions & variables allTests = do testMsg "TEST SUITES FOR ASSIGNMENT 3 FUNCTIONS & VARIABLES" test_evens test_max2 test_almostMax test_primes main = printResults allTests