22
Dec 2013
On Computer Technology
Update Dec 2017: Dear reader, this post was written in a time when Stack did not exist and Haskell users had to deal with cabal directly. For most intents and purposes, you will have a much better experience using Stack.
That being said, the content of this post should still be valid.
If there is one serious pain point I’ve always felt about Haskell, it is the lack of documentation, or if documentation available, it’s usually very terse and feels like it’s meant more for experts than for beginners.
This short article will show you how to install test dependencies for a cabalized project using cabal. The longer version is centred around Yesod, but should be generally applicable. There is a tldr version available below.
In short, suppose you have a cabalized project, and somehow when you run
its test suite, cabal complains about missing dependencies. Now, inside
the .cabal
file of the project, you should find a section beginning with
a line that looks something like this:
test-suite test
and below it, there are some build-depends
that look like libraries meant
for testing.
If so, then you are in luck. Simply execute the following commands:
cabal configure --enable-tests
cabal install --only-dependencies --enable-tests
And cabal will go on to install the test dependencies. Once that is done, you should be able to run the test suite.
For a longer version of how I derived the above, read on.
I was fiddling around with setting up a Yesod scaffolded site, and it went like this:
yesod init
cd yesodtry && cabal sandbox init && cabal install && yesod devel
So my project is named yesodtry
. Everything went smoothly, and the
Yesod scaffolding comes with a "demo" site, that looks like
this:
I noticed the yesod test
line, and curiosity got the better of me.
So I proceeded to enter yesod test
onto the command line, and this
was what I got:
Resolving dependencies...
Configuring yesodtry-0.0.0...
cabal: At least the following dependencies are missing:
hspec -any, yesod-test ==1.2.*
Ok, but I noticed that inside yesodtry.cabal
, there is a test-suite test
section, that looks like this:
test-suite test
type: exitcode-stdio-1.0
main-is: main.hs
hs-source-dirs: tests
ghc-options: -Wall
build-depends: base
, yesodtry
, yesod-test >= 1.2 && < 1.3
, yesod-core
, yesod
, persistent
, persistent-sqlite
, resourcet
, monad-logger
, transformers
, hspec
Notice the yesod-test >= 1.2 && < 1.3
line. So somehow cabal is not
installing that dependency. Out of desperation, I tried
cabal build test
, and I got:
cabal: Cannot build the test suite 'test' because test suites are not enabled.
Run configure with the flag --enable-tests
Ok, so it’s telling me to run cabal configure --enable-tests
. Below
is its output:
Resolving dependencies...
Configuring yesodtry-0.0.0...
cabal: At least the following dependencies are missing:
hspec -any, yesod-test ==1.2.*
which was the exact same output I got from running yesod test
!!!
So it seems like we’re in a vicious cycle here, with no way out…
So I proceeded to ask a question on stack overflow. After a few minutes, no one responded, and I could not find similar questions. A lucky google search yielded the following link:
https://groups.google.com/forum/#!topic/haskell-cafe/SFoNwaq8wdc
Which is an announcement for the release of cabal 1.18.0, and seemingly has nothing to do with our problem, until the following lines in the announcement:
* GHCi support. It's now much easier to use ghci when developing your
packages, especially if those packages require preprocessors (e.g.
hsc2hs).
Here's how working on a package might look like using the new features:
# Only once:
cabal sandbox init
cabal install --only-dependencies --enable-tests
# Configure, build, and run tests:
cabal test # now implies configure and build
# Play around with the code in GHCi:
cabal repl
In particular, the cabal install --only-dependencies --enable-tests
line.
Could that be the magic one liner needed to solve our problems? Fortunately,
yes.
So I proceeded with:
cabal install --only-dependencies --enable-tests
and cabal goes on to install the dependencies for the test-suite test
section.
Then, I proceeded to run:
yesod test
And here’s the last few lines of output:
Linking dist/build/test/test ...
Building yesodtry-0.0.0...
Preprocessing library yesodtry-0.0.0...
In-place registering yesodtry-0.0.0...
Preprocessing test suite 'test' for yesodtry-0.0.0...
Linking dist/build/test/test ...
Running 1 test suites...
Test suite test: RUNNING...
Test suite test: PASS
Test suite logged to: dist/test/yesodtry-0.0.0-test.log
1 of 1 test suites (1 of 1 test cases) passed.
And I felt a sense of accomplishment… even though I wasn’t really interested in learning how to test a yesod web app at this point in time.
Disclaimer: Opinions expressed on this blog are solely my own and do not express the views or opinions of my employer(s), past or present.