QuickCheck is one of the libraries, that makes Haskell awesome. Conventionally, testing boils down to writing a number of separate test-cases to express different assertions about a particular piece of code. Testing like that is possible in Haskell (with HUnit), but QuickCheck’s approach is much more subtle …

Instead of individual test-cases, one has to come up with universal properties, the function being tested is thought to satisfy. Universal means, that the function satisfies the property, regardless of the arguments passed to it. Thus, QuickCheck can repeatedly apply the function to randomly generated arguments and check whether the property holds or not.

The test fails, if the property turns out to be falsifiable (i.e. the function violates the proposed property at least once). Otherwise, the test succeeds.

Let me illustrate how this works with a simple example. Suppose, we want to verify that the following function is correct:

1
2

double :: (Integral a) => a -> a
double n = 2 * n

To get started, we need to find an universal property of `double`

. I can think
of plenty of suitable properties, but for now, let’s use the following:

`double`

’s return value is always an even number.

Obvious, right? The best thing about it, is that we don’t have to implement it
ourselves. Haskell already ships with a predicate function to determine whether
a number is even or not. Unsurprisingly, it’s called `even`

:

1

even :: Integral a => a -> Bool

Okay, we now have everything we need to define the property itself:

1
2

prop_doubleEven :: Integer -> Bool
prop_doubleEven n = even (double n)

`prop_doubleEven`

is the function being called by QuickCheck. Its name has to
start with `prop_`

and its return value has be of type `Bool`

. All the arguments
are randomly generated by QuickCheck. Finally, we can execute all tests as
follows:

1
2

return []
main = $(quickCheckAll)

As expected, QuickCheck informs us that all tests have passed (i.e.
`prop_doubleEven`

is not falsifiable):

1
2

=== prop_doubleEven from Double.hs:9 ===
+++ OK, passed 100 tests.

That was easy ;)

Here’s the complete code:

1
2
3
4
5
6
7
8
9
10
11
12
13

{-# LANGUAGE ScopedTypeVariables, TemplateHaskell #-}
module Double where
import Test.QuickCheck.All
double :: Integer -> Integer
double n = 2 * n
prop_doubleEven :: Integer -> Bool
prop_doubleEven n = even (double n)
return []
main = $(quickCheckAll)

In this post, I’ve only outlined the most basic usage of QuickCheck. In reality,
there’s **a lot** more to say about it. But, let’s leave that for another day.