How to automatically build test modules with stack? - haskell

I have this Spec.hs:
import qualified OtherSpec
main :: IO ()
main = do
putStrLn "Test..."
OtherSpec.main
And I am planning to add more test suites from other modules to its main.
When I run tests as:
$ stack test --file-watch
A few things happen:
Tests are re-run when OtherSpec.hs is changed, but the test executable is not rebuilt.
When I change Spec.hs test executable is rebuilt and changes in OtherSpec.hs is also picked.
Is there a way to trigger a rebuild when OtherSpec.hs changes?
I am using stack version 0.1.2.0.

Related

How to compile an executable from Haskell Stack build?

|-aseCswk2
|-app
|-Main.hs
|-src
|-Libs.hs
|-test
|-Spec.hs
|-aseCswk2.cabal
|-Setup.hs
|-package.yaml
...
So i have a Haskell project that uses a Stack build system and is laid out as the example above. If i use $ stack test then my functions in my Libs.hs file are tested with the cases in my Spec.hs file. If i use $ stack build then my file builds successfully and i can use the functions inside $ stack ghci.
However, i want to create an executable of the my Main.hs file but don't know how this is possible. I have tried compiling it using $ ghc Main.hs inside the app directory but get an error saying 'Failed to load interface for Lib' even though i have included it as an import. I have also tried $stack build aseCswk2:exe:aseCswk2-exe but no .o files are created to run.
Haskell-stack builds the executable in the hidden .stack-work directory. You can find out where the binaries are located that stack uses with:
$ stack path --local-install-root
/haskell/app/.stack-work/install/x86_64-linux/3fa5b3c3fbcd473981eef72c68d572129654cbb7c23af146b50d90e29c41b62f/8.6.5
In this directory, there is, if you build the application, a bin/ directory where the binary is located that has been built.
You can also run the application with:
$ stack run

Stack: Compile stand-alone source file

Once you've installed Stack, you can use it to install GHC for you. Great!
...now how do I compile a file with it?
To be clear: What you're supposed to do is write a package specification and have Stack build that. But surely there must be a way to trivially compile a tiny helper file inside that project? It seems silly to have to construct an entire project just so I can build a tiny helper program and have it easily runnable from the shell.
I know I can run any Haskell file using Stack. But I cannot for the life of me figure out how to compile the thing...
You can use stack ghc -- <file names> to compile and link a set of files (it's briefly mentioned in Stack's user guide):
You'll sometimes want to just compile (or run) a single Haskell source file, instead of creating an entire Cabal package for it. You can use stack exec ghc or stack exec runghc for that. As simple helpers, we also provide the stack ghc and stack runghc commands, for these common cases.
The -- is to ensure the arguments we pass are sent to ghc, rather than being parsed as arguments to stack exec. It's the same thing as when trying to pass arguments to an executable you've made using the normal stack toolchain: stack exec myExe -foo passes -foo to exec, not myExe, stack exec myExe -- -foo behaves as desired.
For example:
Bar.hs
module Bar where
bar :: Int
bar = 5
Foo.hs
import Bar
main :: IO ()
main = print bar
Compilation (don't even need to specify Bar.hs in the build files, it's sourced automatically):
> stack ghc -- Foo.hs
[1 of 2] Compiling Bar ( Bar.hs, Bar.o )
[2 of 2] Compiling Main ( Foo.hs, Foo.o )
Linking Foo ...
> ./Foo
5
There's no problem with dependencies either - it looks like all the packages installed locally are available to the build (you can use containers or QuickCheck without any additional build params).

How to load tests in ghci with stack

I created a very simple project with stack. It contains: an executable, a library and test targets in the associated cabal file. When I load the code to ghci via stack ghci, I can't access test there, even if they are in separate module. Is there any way to use it in such a way?
Try stack ghci (your project name):(the test suite name). Then you should be able to enter main and your tests will run.
Example:
If your .cabal project file had the following values:
name: ExampleProject
...
test-suite Example-test
Then the command to run would be stack ghci ExampleProject:Example-test
(edit suggested by #Chris Stryczynski)
To watch the test and src directories so they are updated when you reload with :r, run:
stack ghci --ghci-options -isrc --ghci-options -itest ExampleProduct:Example-test

Generate coverage report with stack

I want to generate code coverage report using Stack. I run command that
amounts to (omitting options passed to test suite via --test-arguments):
$ stack test --coverage
This performs the testing and then outputs the following:
Error: The coverage report for myproject's test-suite "tests" did not
consider any code. One possible cause of this is if your test-suite builds
the library code (see stack issue #1008). It may also indicate a bug in
stack or the hpc program. Please report this issue if you think your
coverage report should have meaningful results.
I think it should (this creates empty report). GHC options are identical for
all components of my package. There is no need for test suite to rebuild the
library. After all, if Cabal can generate the report, Stack should be able
to do it given the same Cabal config or am I mistaken?
I've opened
an issue on Stack
GitHub repo as suggested.
After a while I decided to create good old sandbox and generate the report
using Cabal instead (I really need to see the report, you know). It worked
previously, but now I get:
$ cabal sandbox init
… <everything OK>
$ cabal update
… <everything OK>
$ cabal install --only-dependencies --enable-tests
… <everything OK>
$ cabal configure --enable-tests --enable-coverage
… <everything OK>
$ cabal build
… <everything OK>
$ cabal test
Running 2 test suites...
Test suite tests: RUNNING...
Test suite tests: PASS
Test suite logged to: dist/test/myproject-0.1.0-tests.log
hpc: can not find HUnit_DDLSMCRs3jyLBDbJPCH01j/Test.HUnit.Lang in ["./.hpc","./dist/hpc/vanilla/mix/myproject-0.1.0","./dist/hpc/vanilla/mix/tests"]
What? I've never seen this, although I generated many reports
before. Someone up there just decided that I won't get that report today,
it seems.
Do you know how to generate coverage report using Stack? Has anyone
succeeded at this?
In my case I was still getting this error. Running:
stack clean
stack test --coverage
solved the problem, as reported here.
Recent changes upstream fixed it. Should be resolved for users of 0.1.7.0 and later.

Haskell doctest does not load package managed with cabal-dev

I am trying to test my project which uses "data-binary-ieee754" with doctests.
I uses cabal-dev, instead of cabal, to manage package dependencies.
I can build the project, but doctest seems not to recognize that package.
doctests definition in .cabal:
test-suite doctests
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: doctests.hs
ghc-options: -Wall -threaded
build-depends: base,
doctest >= 0.7,
data-binary-ieee754
test/doctests.hs:
module Main where
import Test.DocTest
main :: IO ()
main = doctest ["src/Pattern.hs"]
The error message for cabal-dev test doctests is:
Running 1 test suites...
Test suite doctests: RUNNING...
src/Pattern.hs:13:8:
Could not find module `Data.Binary.IEEE754'
Use -v to see a list of the files searched for.
Test suite doctests: FAIL
Test suite logged to: dist/test/othello-0.1.0-doctests.log
0 of 1 test suites (0 of 1 test cases) passed.
I tried to add some options to doctests.hs, like
main = doctest ["--optghc=-Lcabal-dev/lib",
"--optghc=-packagedata-binary-ieee754",
"src/Pattern.hs"]
but the result is
Running 1 test suites...
Test suite doctests: RUNNING...
doctests: <command line>: cannot satisfy -package data-binary-ieee754
(use -v for more information)
Test suite doctests: FAIL
Test suite logged to: dist/test/othello-0.1.0-doctests.log
0 of 1 test suites (0 of 1 test cases) passed.
Tell me how to do this correctly. Thanks.
I found the answer by myself.
http://hackage.haskell.org/trac/ghc/ticket/6133 was helpful.
main :: IO ()
main = doctest ["--optghc=-Lcabal-dev/lib",
"--optghc=-packagedata-binary-ieee754",
"--optghc=-package-conf=cabal-dev/packages-7.4.1.conf",
"src/Pattern.hs"]
Just to update this answer a bit, doctest now allows you to call ghc options directly.
You can also load a sandboxed package database and call from cabal.
doctest [ "-package-db .cabal-sandbox/x86_64-linux-ghc-7.10.3-packages.conf.d"
, "-isrc"
, "src/<path-to-file>"]
This cleared up missing package problems for me.

Resources