Published 30th of January, 2015, by Nikos Baxevanis. Tagged as haskell, quickcheck.

QuickCheck setup in Haskell

Cabal is the build system for Haskell, it also doubles as a package manager. Create a .cabal file:

-- samples-quickcheck.cabal

Name:                   samples-quickcheck
Version:                0.0.0
Cabal-Version:          >= 1.10
Build-Type:             Simple

Library
  Default-Language:     Haskell2010
  HS-Source-Dirs:       tests
  GHC-Options:          -Wall
  Build-Depends:        base
                      , hspec
                      , QuickCheck

Test-Suite spec
  Type:                 exitcode-stdio-1.0
  Default-Language:     Haskell2010
  Hs-Source-Dirs:       tests
  Ghc-Options:          -Wall
  Main-Is:              Spec.hs
  Build-Depends:        base
                      , hspec
                      , QuickCheck

Enable automatic Hspec discovery, so that each module ending with Spec can be automatically considered as a test module:

-- tests/Spec.hs
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}

Add a simple (icebreaker) test, because there’s always a bit of work involved in getting everything up and running:

-- tests/GettingStartedSpec.hs
module GettingStartedSpec (spec) where

import Test.Hspec
import Test.Hspec.QuickCheck

spec :: Spec
spec = do
    describe "icebreaker" $ do
        prop "icebreaker" $ \x y ->
            add x y == add y x

add :: Int -> Int -> Int
add x y = x + y

Create a Cabal sandbox, install dependencies, build the package, and enable the tests, by running the following commands in a terminal:

cabal update                      # Download the most recent list of packages
cabal install cabal-install       # Optional, can be prompted by cabal update

cabal sandbox init                # Initialise the sandbox
cabal install --only-dependencies # Install dependencies into the sandbox
cabal build                       # Build your package inside the sandbox

cabal configure --enable-tests    # Enable the test suites

Run the tests via Cabal’s built-in test runner:

cabal test

Building samples-quickcheck-0.0.0...
Preprocessing library samples-quickcheck-0.0.0...
In-place registering samples-quickcheck-0.0.0...
Preprocessing test suite 'spec' for samples-quickcheck-0.0.0...
[1 of 2] Compiling GettingStartedSpec (tests\GettingStartedSpec.hs, dist\buil...
[2 of 2] Compiling Main (tests\Spec.hs, dist\build\spec\spec-tmp\Main.o)...
Linking dist\build\spec\spec.exe ...
Running 1 test suites...
Test suite spec: RUNNING...
Test suite spec: PASS
Test suite logged to: dist\test\samples-quickcheck-0.0.0-spec.log
1 of 1 test suites (1 of 1 test cases) passed.

See the test failing, as a form of Double Entry Bookkeeping:

-- Change:
add x y == add y x

-- To:
add x y == add 0 1
cabal test

Building samples-quickcheck-0.0.0...
Preprocessing library samples-quickcheck-0.0.0...
In-place registering samples-quickcheck-0.0.0...
Preprocessing test suite 'spec' for samples-quickcheck-0.0.0...
[1 of 2] Compiling GettingStartedSpec (tests\GettingStartedSpec.hs,...
[2 of 2] Compiling Main (tests\Spec.hs, dist\build\spec\spec-tmp\Main.o)...
Linking dist\build\spec\spec.exe ...
Running 1 test suites...
Test suite spec: RUNNING...

GettingStarted
  icebreaker
    icebreaker FAILED [1]

Failures:

  1) GettingStarted.icebreaker icebreaker
       Falsifiable (after 1 test and 1 shrink):
       0
       0

Randomized with seed 1531351472

Finished in 0.0000 seconds
1 example, 1 failure
Test suite spec: FAIL
Test suite logged to: dist\test\samples-quickcheck-0.0.0-spec.log
0 of 1 test suites (0 of 1 test cases) passed.

To use QuickCheck interactively, start a REPL by doing:

cabal repl spec

In the above command, spec is just the name of the test-suite, as declared in the .cabal file.

For convenience, all the above are also available on GitHub.

References



Wish to comment?

You can comment on this post on GitHub. Alternatively, you can discuss this post on Twitter or elsewhere with a permalink. Ping me with the link, and I may respond.