Guard::Haskell
automatically runs your specs
% cabal install hspec
% gem install guard-haskell
For explanation what guard
is and how to use it, please refer to the guard manual
guard-haskell
uses hspec
to run specs and check results, so it makes
some assumptions about your code organization and style:
-
hspec
is your testing framework of choice; therefore, -
hspec-discover
organizes your specs
When you type guard
in the terminal, guard-haskell
fires up a cabal repl
instance
to talk to, running (parts of) examples when files are modified.
For guard-haskell
to be ready to work we need a test suite (conventionally named "spec")
defined in the cabal file and a Guardfile (you can get one by running guard init haskell
)
Marcin Gryszko has put together a sample project where guard-haskell
is set up and can
be tinkered with.
A typical haskell project:
guard :haskell do
watch(%r{test/.+Spec\.l?hs$})
watch(%r{src/.+\.l?hs$})
watch(%r{\.cabal$})
end
Another haskell project with a non-standard layout running cabal repl
:
cmd = "cabal repl spec --ghc-options='-ignore-dot-ghci -DTEST'"
guard :haskell, all_on_start: true, cmd: cmd do
watch(%r{test/.+Spec\.l?hs$})
watch(%r{lib/.+\.l?hs$})
watch(%r{bin/.+\.l?hs$})
watch(%r{\.cabal$})
end
Yet another haskell project running ghci
as a REPL:
cmd = "cabal exec ghci test/Spec.hs"
guard :haskell, all_on_start: true, all_on_pass: true, cmd: cmd do
watch(%r{test/.+Spec\.l?hs$})
watch(%r{src/.+\.l?hs$})
end
It's also advised to have a trivial Gemfile
in the repository for
bundler exec guard
to be able to pick the correct versions of the dependencies:
source "https://rubygems.org"
gem "guard-haskell", "~>2.1"
Guard::Haskell
has a bunch of options:
Run all examples on start (default: false
).
Run all examples when a failed spec passes again (default: false
).
Rerun only failed examples until they pass (default: true
).
The command to run in the background as a REPL (default: cabal repl spec
)
Unfortunately, testing such applications with guard-haskell
is basically impossible
because ghci
uses GHC API
too. Sooner or later you will see something like:
GHCi runtime linker: fatal error: I found a duplicate definition for symbol
HUnitzm1zi2zi5zi2_TestziHUnitziBase_zdwzdcshowsPrec_slow
whilst processing object file
/home/maksenov/.cabal/lib/HUnit-1.2.5.2/ghc-7.6.2/HSHUnit-1.2.5.2.o
This could be caused by:
* Loading two different object files which export the same symbol
* Specifying the same object file twice on the GHCi command line
* An incorrect `package.conf' entry, causing some object to be
loaded twice.
GHCi cannot safely continue in this situation. Exiting now. Sorry.
Fragile concurrent access is a known limitation of the GHC API
, which hopefully will be eventually fixed.