liveBook · Manning

QuickCheck

As explained in Learn Haskell by Example

QuickCheck is a Haskell library for property-based testing that generates test data and checks properties across many inputs.

QuickCheck is a Haskell library for property-based testing: write a property that should hold for all inputs, then check it against automatically generated cases. It is especially useful for pure functions, where correctness can be expressed by comparing outputs for the same inputs. Add QuickCheck >= 2.0 to package.yaml; Stack resolves the dependency when building or starting the REPL. section 9.0 section 9.2.1 section 9.3

ghci> import Test.QuickCheck
ghci> prop_rot13Symm s = s == rot13 (rot13 s)
ghci> :t prop_rot13Symm
prop_rot13Symm :: String -> Bool
ghci> quickCheck prop_rot13Symm
+++ OK, passed 100 tests.

A property can be an ordinary function returning Bool. quickCheck turns checking it into an IO action and generates String inputs automatically. section 9.3.1

Use the prop_ prefix for properties. A passing result means the generated tests did not falsify the property; it is not a proof. When a property fails, QuickCheck reports a counterexample and shrinks it to a simpler failing input, making a bug easier to inspect. section 9.3.1 section 9.4.3

QuickCheck provides the pieces needed to tailor test data and test behavior:

  • Generate data with Gen and generate. Build generators with choose, elements, oneof, listOf, vectorOf, shuffle, and suchThat. section 9.4.1
  • Use arbitrary when an Arbitrary instance supplies generation for a type; define arbitrary and shrink for custom types such as associative maps. section 9.4.1 section 9.4.3
  • Use forAll to connect a custom generator to a property, such as generating a nonempty alphabet, a bounded rotation amount, and a character from that alphabet. section 9.4.1
  • Inspect generated cases with verbose, summarize them with collect or label, and require distributions with cover. section 9.5.1
  • Add preconditions with ==>. Check discarded cases, since narrow preconditions can leave too little useful test data. section 9.5.1

Diagnosing a misleading sorting test

A sorting property can appear to pass even for id when GHC defaults the element type to (). verbose exposes the trivial inputs. Give the property an explicit type such as [Int] -> Bool, then use collect or label to see empty lists and cover to require enough non-trivial cases. section 9.5 section 9.5.1

For a Stack test suite, place test code under test and run stack test. quickCheckAll uses Template Haskell to find prop_-prefixed properties in a module; combine suite results in Main and return a success or failure exit code. section 9.5.3 section 9.6

How Learn Haskell by Example covers it

How deep it goes
Explains property execution, generators, Arbitrary instances, shrinking, coverage modifiers, and Stack suites while deferring custom Testable instances.
Examples
Uses rot13 symmetry, alphabet rotation closedness, sorting predicates, associative maps, and multi-module Stack test suites.
What it assumes
Assumes basic Haskell functions, types, IO actions, and do notation while introducing QuickCheck’s testing APIs from first use.
What you can do after
Apply it via QuickCheck and Stack to generate inputs, diagnose weak properties, shrink failures, and run property suites.
How it connects
Connects property testing with referential transparency, Gen, Arbitrary, shrinking, type defaulting, Template Haskell, and Stack.

Also explained in

Compare how 3 books explain QuickCheck →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Haskell by Example. The section links point to the parts of the book it draws on.