QuickCheck setup in Haskell

30 Jan 2015

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