VF1
VF1

Reputation: 1652

How to expect exceptions with QuickCheck2

I've been trying to pick up Haskell recently, but I am having some difficulty with QuickCheck2 (which I'm trying to learn while coding up the 99 problems). I've looked at this question along with related ones on the matter.

Like OP from the aforementioned question, I'm interested in finding out whether it is possible for QuickCheck2 to expect exceptions. I know this is possible with QuickCheck 1. Some googling around led me to the following version of my code to test a myLast function which returns the last element of a list:

prop_myLast :: [Int] -> Bool
prop_myLast [] = expectFailure . myLast $ []
prop_myLast xs = myLast xs == last xs

Of course, this (1) does not typecheck, since expectFailure returns a Property and (2) requires an import from v1 of QuickCheck. Regarding (1) I don't really see how to make this work - I tried looking up how to catch exceptions on my own but was met with more difficulty because this started bringing in the IO monad. With respect to (2) I don't know if bringing in the expectFailure function is a good idea in the first place - could anyone experienced with the system tell me if I'm supposed to be using components from both v1 and v2? If not, where is the analogous expectFailure for v2 of QuickCheck?

Upvotes: 5

Views: 496

Answers (1)

ErikR
ErikR

Reputation: 52049

You use expectFailure like this:

prop :: Int -> Bool
prop x = x + 1 == x  -- should always be False

main = quickCheck (expectFailure prop)

However, expectFailure only tests that there is at least one test case which fails - i.e. it really expects your code to fail. You want QuickCheck to ignore any failures in the event that it passes the empty list to prop_myLast.

One way to do this is with the ==> operator:

prop_myLast :: [Int] -> Property
prop_myLast xs = not (null xs) ==> myLast xs == last xs

Another example:

prop_cubed :: Int -> Property
prop_cubed x = (x > 1) ==> x^3 > x   -- note: not true for negative values so don't
                                     --       test those cases

Quickcheck will discard generated test cases which do not match the conditional.

Update: One way of explicitly testing the [] case is:

quickCheck $ expectFailure $ seq (myLast []) True

The expression seq a True will return True unless a throws an exception or diverges.

Upvotes: 4

Related Questions