Less fragmented properties with Hedgehog

In this post, I’ll be porting a property-based test from QuickCheck 2 and from FsCheck 2 to Hedgehog. See this post for a brief introduction to Hedgehog.

Setup phase (de)fragmentation

When writing a property, essentially we test a unit in isolation and so some of the practices for traditional unit-tests can also apply to property-based tests. One common practice is to structure each test in three distinct parts executed in sequence

  1. Setup phase
  2. Exercise phase
  3. Verification phase

In classic TDD these phases are called Arrange, Act, Assert, while in BDD they’re called Given, When, Then.

Examples in Haskell

Often the setup phase can become fragmented, as shown in the following example (source) usually because of the ‘noise’ that’s generated because of the Arbitrary required by forAll:

Notice how the setup phase becomes less fragmented with Hedgehog, as shown in the following example (source):

It can be worth pointing out also the fine-grained control we can have over the scope of generated values with the Range combinators1.

Examples in F#

FsCheck is similar to QuickCheck, so its forAll needs an Arbitrary as well, as shown below (source):

Here’s the same example written with Hedgehog (source):

Notice how the setup phase becomes less fragmented with Hedgehog, and how the property Computation Expression makes it easier to separate each distinct phase of the property-based test.

  1. The Range combinators aren’t available yet in the F# version. They are tracked though by this GitHub item.