module Spec where import Test.QuickCheck import Data.List((\\), sort) -- Spec: use specification based development techniques -- Spec.Test: formulate and test properties about the program -- Spec.Prove: reason about correctness of functional programs -- Spec.Trans: transform programs on the basis of reasoning -- Below is an attempt at a QuickCheck test suite for |qsort :: Ord a => [a] -> [a]|. qsort :: Ord a => [a] -> [a] qsort = sort prop_minimumBad xs = head (qsort xs) == minimum xs prop_orderedBad xs = ordered (qsort xs) where ordered [] = True ordered (x:y:xs) = x <= y && ordered (y:xs) prop_permutationBad xs = permutation xs (qsort xs) where permutation xs ys = null (xs \\ ys) && null (ys \\ ys) -- Find and correct at least one bug per property in the test suite. {- quickCheck (prop_minimumBad :: [Int] -> Bool) *** Failed! Exception: 'Prelude.head: empty list' (after 1 test): [] -} prop_minimum :: [Int] -> Property prop_minimum xs = not (null xs) ==> head (qsort xs) == minimum xs -- Write a |main| function which tests the three properties (for lists of integers) using QuickCheck. prop_ordered :: [Int] -> Bool prop_ordered xs = ordered (qsort xs) where ordered [] = True ordered [x] = True ordered (x:y:xs) = x <= y && ordered (y:xs) prop_permutation :: [Int] -> Bool prop_permutation xs = permutation xs (qsort xs) where permutation xs ys = null (xs \\ ys) && null (ys \\ xs) main = do quickCheck prop_minimum quickCheck prop_ordered quickCheck prop_permutation {- Write a sized generator (|sizedList :: Gen a -> Gen [a]|) for random lists. Make sure the list length is random (but bounded by the current size). -} sizedList :: Gen a -> Gen [a] sizedList g = sized $ \n -> do size <- choose (0, n) myVector size g myVector :: Int -> Gen a -> Gen [a] myVector n g = sequence (replicate n g) ---------------------------------------------------------------- -- End of exam question -- -------------------------------------------------------------- testBad = do quickCheck (prop_minimumBad :: [Int] -> Bool) quickCheck (prop_orderedBad :: [Int] -> Bool) quickCheck (prop_permutationBad :: [Int] -> Bool) ---------------- -- Sanity check sizedList' :: Gen a -> Gen (Int, [a]) sizedList' g = sized $ \n -> do size <- choose (0, n) fmap ((,) n) $ myVector size g