how to write cabal package file for executable with unit tests?

What's the preferred way to write a cabal configuration file for a package that contains an executable and a test suite? The only thing I've found that seems to work is to put a thin wrapper Main.hs into the executable, put all of the actual code into the library, and then have the test-suite include the library in its build-depends list. This works, but I find it mildly annoying that I have to separate the code out in this fashion -- especially since the unit tests require me to expose modules in my library that aren't really part of the library's public interface. In more detail: This is a follow-up to a thread I posted back on Feb 2; you can see it on GMane at http://thread.gmane.org/gmane.comp.lang.haskell.cafe/109374. The original example (tarball attached to the first message in that thread) was a package structured as a library with unit tests. After acting on Erik's suggestion to put the library and test-suite source in different directories, I was able to compile the library without the type error I originally mentioned. However, this isn't really the package structure I want. The package is actually intended to produce a standalone executable, not a library. My original example used a library for reasons that I don't honestly remember -- I think I more or less stumbled upon that structure as something that more or less worked, given the difficulty of getting Cabal, test suites, Happy, and Alex to all work together well. So I tried replacing the "Library" section of the cabal file with an "Executable" section (sample tarball attached), but then I can't get the tests to compile. If I leave sample as a build-depends for the test-suite, then "cabal configure --enable-tests" fails with Preprocessing test suite 'sample-tests' for sample-0.4... <command line>: cannot satisfy -package-id sample-0.4-inplace (use -v for more information) If I take sample out of the build-depends list for the test-suite, then "cabal configure --enable-tests" works, but "cabal build" fails: test-src/RunTests.hs:8:8: Could not find module `Parser' It is a member of the hidden package `ghc-7.6.3'. Perhaps you need to add `ghc' to the build-depends in your .cabal file. Use -v to see a list of the files searched for. Either way, "cabal configure && cabal build" works fine; it's only when I try to build the test suite that things break down. Thanks, Richard

If you don't want a separate library, use the second Erik's suggestion
from that thread.
* Richard Cobbe
What's the preferred way to write a cabal configuration file for a package that contains an executable and a test suite? The only thing I've found that seems to work is to put a thin wrapper Main.hs into the executable, put all of the actual code into the library, and then have the test-suite include the library in its build-depends list.
This works, but I find it mildly annoying that I have to separate the code out in this fashion -- especially since the unit tests require me to expose modules in my library that aren't really part of the library's public interface.
In more detail:
This is a follow-up to a thread I posted back on Feb 2; you can see it on GMane at http://thread.gmane.org/gmane.comp.lang.haskell.cafe/109374. The original example (tarball attached to the first message in that thread) was a package structured as a library with unit tests. After acting on Erik's suggestion to put the library and test-suite source in different directories, I was able to compile the library without the type error I originally mentioned.
However, this isn't really the package structure I want. The package is actually intended to produce a standalone executable, not a library. My original example used a library for reasons that I don't honestly remember -- I think I more or less stumbled upon that structure as something that more or less worked, given the difficulty of getting Cabal, test suites, Happy, and Alex to all work together well.
So I tried replacing the "Library" section of the cabal file with an "Executable" section (sample tarball attached), but then I can't get the tests to compile. If I leave sample as a build-depends for the test-suite, then "cabal configure --enable-tests" fails with
Preprocessing test suite 'sample-tests' for sample-0.4... <command line>: cannot satisfy -package-id sample-0.4-inplace (use -v for more information)
If I take sample out of the build-depends list for the test-suite, then "cabal configure --enable-tests" works, but "cabal build" fails:
test-src/RunTests.hs:8:8: Could not find module `Parser' It is a member of the hidden package `ghc-7.6.3'. Perhaps you need to add `ghc' to the build-depends in your .cabal file. Use -v to see a list of the files searched for.
Either way, "cabal configure && cabal build" works fine; it's only when I try to build the test suite that things break down.
Thanks,
Richard
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Mon, Feb 17, 2014 at 12:52:41AM +0200, Roman Cheplyaka wrote:
If you don't want a separate library, use the second Erik's suggestion from that thread.
I tried that, and I seem to still be missing something. With Test-Suite sample-tests main-is: RunTests.hs hs-source-dirs: test-src, src other-modules: Ast, Parser, Scanner type: exitcode-stdio-1.0 default-language: Haskell2010 build-depends: base, array, containers, HUnit then "cabal configure --enable-tests && cabal build" results in the following error: test-src/RunTests.hs:8:8: Could not find module `Parser' It is a member of the hidden package `ghc-7.6.3'. Perhaps you need to add `ghc' to the build-depends in your .cabal file. Use -v to see a list of the files searched for. If I remove "src" from the hs-source-dirs line, then cabal complains that it can't find source for Ast. If I put "src" back and remove the other-modules line, I get the same "Could not find module 'Parser'" error message from above. * * * * * These seem to be pretty basic questions to me, but they also don't seem to be in the Cabal manual anywhere. Is there somewhere else I should be looking? Richard
* Richard Cobbe
[2014-02-16 17:15:25-0500] What's the preferred way to write a cabal configuration file for a package that contains an executable and a test suite? The only thing I've found that seems to work is to put a thin wrapper Main.hs into the executable, put all of the actual code into the library, and then have the test-suite include the library in its build-depends list.
This works, but I find it mildly annoying that I have to separate the code out in this fashion -- especially since the unit tests require me to expose modules in my library that aren't really part of the library's public interface.

Can you upload your code somewhere (e.g. github)? It would be much
easier for us to troubleshoot.
But please don't attach archives to mailing list messages.
* Richard Cobbe
On Mon, Feb 17, 2014 at 12:52:41AM +0200, Roman Cheplyaka wrote:
If you don't want a separate library, use the second Erik's suggestion from that thread.
I tried that, and I seem to still be missing something.
With
Test-Suite sample-tests main-is: RunTests.hs hs-source-dirs: test-src, src other-modules: Ast, Parser, Scanner type: exitcode-stdio-1.0 default-language: Haskell2010 build-depends: base, array, containers, HUnit
then "cabal configure --enable-tests && cabal build" results in the following error:
test-src/RunTests.hs:8:8: Could not find module `Parser' It is a member of the hidden package `ghc-7.6.3'. Perhaps you need to add `ghc' to the build-depends in your .cabal file. Use -v to see a list of the files searched for.
If I remove "src" from the hs-source-dirs line, then cabal complains that it can't find source for Ast.
If I put "src" back and remove the other-modules line, I get the same "Could not find module 'Parser'" error message from above.
* * * * *
These seem to be pretty basic questions to me, but they also don't seem to be in the Cabal manual anywhere. Is there somewhere else I should be looking?
Richard
* Richard Cobbe
[2014-02-16 17:15:25-0500] What's the preferred way to write a cabal configuration file for a package that contains an executable and a test suite? The only thing I've found that seems to work is to put a thin wrapper Main.hs into the executable, put all of the actual code into the library, and then have the test-suite include the library in its build-depends list.
This works, but I find it mildly annoying that I have to separate the code out in this fashion -- especially since the unit tests require me to expose modules in my library that aren't really part of the library's public interface.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi Richard,
Where is your Parser module located?
Remember that your code will be compiled twice this way. What is, in
my opinion, a better setup, is put the shared code in a library (like
you had), and then have a shallow executable in the same package that
depends on the library. The test-suite can then also depend on the
library. All three should have distinct source dirs.
Having most functionality in a library is a good design principle
anyway: it makes it easier to re-use it in a different way later, and
makes sure you think about API boundaries and such.
Regards,
Erik
On Mon, Feb 17, 2014 at 2:26 AM, Richard Cobbe
On Mon, Feb 17, 2014 at 12:52:41AM +0200, Roman Cheplyaka wrote:
If you don't want a separate library, use the second Erik's suggestion from that thread.
I tried that, and I seem to still be missing something.
With
Test-Suite sample-tests main-is: RunTests.hs hs-source-dirs: test-src, src other-modules: Ast, Parser, Scanner type: exitcode-stdio-1.0 default-language: Haskell2010 build-depends: base, array, containers, HUnit
then "cabal configure --enable-tests && cabal build" results in the following error:
test-src/RunTests.hs:8:8: Could not find module `Parser' It is a member of the hidden package `ghc-7.6.3'. Perhaps you need to add `ghc' to the build-depends in your .cabal file. Use -v to see a list of the files searched for.
If I remove "src" from the hs-source-dirs line, then cabal complains that it can't find source for Ast.
If I put "src" back and remove the other-modules line, I get the same "Could not find module 'Parser'" error message from above.
* * * * *
These seem to be pretty basic questions to me, but they also don't seem to be in the Cabal manual anywhere. Is there somewhere else I should be looking?
Richard
* Richard Cobbe
[2014-02-16 17:15:25-0500] What's the preferred way to write a cabal configuration file for a package that contains an executable and a test suite? The only thing I've found that seems to work is to put a thin wrapper Main.hs into the executable, put all of the actual code into the library, and then have the test-suite include the library in its build-depends list.
This works, but I find it mildly annoying that I have to separate the code out in this fashion -- especially since the unit tests require me to expose modules in my library that aren't really part of the library's public interface.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Mon, Feb 17, 2014 at 11:07:07AM +0100, Erik Hesselink wrote:
Hi Richard,
Where is your Parser module located?
The Happy source for the Parser module is in the src directory with the rest of the files for the executable.
Remember that your code will be compiled twice this way. What is, in my opinion, a better setup, is put the shared code in a library (like you had), and then have a shallow executable in the same package that depends on the library. The test-suite can then also depend on the library. All three should have distinct source dirs.
Having most functionality in a library is a good design principle anyway: it makes it easier to re-use it in a different way later, and makes sure you think about API boundaries and such.
In principle, I agree. However, it's not obvious that there's actually any code that's suitable for re-use in this case (except for stuff I've already moved out to other libraries, in separate Cabal packages). And I'm not sure that I get many of the benefits of thinking about API boundaries, because I have to expose modules from the library if I want to write unit tests for them, even if they're not really part of the library's public interface. However, that seems to be the best way to go, so I'll leave it at that. Thanks! Richard

On 18/02/14 12:57, Richard Cobbe wrote:
And I'm not sure that I get many of the benefits of thinking about API boundaries, because I have to expose modules from the library if I want to write unit tests for them, even if they're not really part of the library's public interface.
Exactly that has bothered me for long. If I want to make a proper cabal package with tests for internal API, I have to expose the internal API (otherwise we get double building). In general, I always recommend exposing all the code in .Internal modules - I often run into problems with packages that don't do this. Yet, the whole re-exporting overhead introduced by this is cumbersome, and it doesn't make haddocks nicer either (e.g. when you come to a page that is full of re-exports). I hope haddock will find a way to make this nicer.

Indeed. Best practices are trending towards making internal Apis public.
But very very clearly making it clear "assume these get breaking changes
every single release. "
On Tuesday, February 18, 2014, Niklas Hambüchen
And I'm not sure that I get many of the benefits of thinking about API boundaries, because I have to expose modules from the library if I want to write unit tests for them, even if they're not really part of the
On 18/02/14 12:57, Richard Cobbe wrote: library's
public interface.
Exactly that has bothered me for long.
If I want to make a proper cabal package with tests for internal API, I have to expose the internal API (otherwise we get double building).
In general, I always recommend exposing all the code in .Internal modules - I often run into problems with packages that don't do this.
Yet, the whole re-exporting overhead introduced by this is cumbersome, and it doesn't make haddocks nicer either (e.g. when you come to a page that is full of re-exports). I hope haddock will find a way to make this nicer. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org javascript:; http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi, Richard Cobbe wrote:
test-src/RunTests.hs:8:8: Could not find module `Parser'
Is the Parser module generated by happy? In this case, maybe you have to add the build-tools: happy line to your test-suite description in the cabal file. Tillmann
participants (6)
-
Carter Schonwald
-
Erik Hesselink
-
Niklas Hambüchen
-
Richard Cobbe
-
Roman Cheplyaka
-
Tillmann Rendel