Skip to content

Instantly share code, notes, and snippets.

@peteanning
Last active December 7, 2021 09:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peteanning/e3cb8c9aef4318cbaf46d5e1abf3d06a to your computer and use it in GitHub Desktop.
Save peteanning/e3cb8c9aef4318cbaf46d5e1abf3d06a to your computer and use it in GitHub Desktop.

Setting up Hspec to TTD your Haskell

Start with ghcup

curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh

This script will download and install the following binaries:

  • ghcup - The Haskell toolchain installer
  • ghc - The Glasgow Haskell Compiler
  • cabal - The Cabal build tool for managing Haskell software
  • stack - (optional) A cross-platform program for developing Haskell projects
  • hls - (optional) A language server for developers to integrate with their editor/IDE

I chose not to install stack as I want cabal because I found this testing framework

Once Cabal is installed:

Create a Project directory

mkdir myProject && cd myProject

If you want the full Cabal experience follow the instructions here which have been sumarised here:

Optional This creates the folder structure and needed files

cabal init

Optional This will build the executable and run it

cabal run

Mandatory for Hspec The next bit is from the HSpec site this creates a hidden package file in the current directory: .ghc.environment.x86_64-darwin-9.0.1 Note the version number of ghc. If you update your version of ghc the following command will need running again

cabal update && cabal install --package-env=. --lib hspec hspec-contrib QuickCheck HUnit

Now create the test spec in Spec.hs for this example

main :: IO ()
main = hspec $ do
  describe "" $ do
    it "returns the first element of a list" $ do
      head [23 ..] `shouldBe` (23 :: Int)

    it "returns the first element of an *arbitrary* list" $
      property $ \x xs -> head (x:xs) == (x :: Int)

    it "throws an exception if used with an empty list" $ do
      evaluate (head []) `shouldThrow` anyExceptio

To run the test: run haskell Spec.hs

Optional Fswatch for Mac OS

If you want your Specs to run every time you make changes in a true Test First Style you could use faswatch or similar.

Fswatch

Installing fswatch

used brew install fswatch

Run this from the project directory where your Haskell files are being edited Setup fswatch to watch changes to Haskell source files and run test specs (I made the following an alias)

fswatch -or *.hs | xargs -n1 -I{} runhaskell *Spec.hs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment