[Haskell-cafe] packages and QuickCheck

Sean Leather leather at cs.uu.nl
Tue Sep 9 10:32:35 EDT 2008

> How do folks like to package up QuickCheck tests for their libraries?  In
>>> the main library?  As a separate repo & package?  Same repo & separate
>>> package?  Keeping tests with the tested code allows testing of non-exported
>>> functionality, but can add quite a lot of clutter.
>> I have QuickCheck properties plus HUnit tests, but I think the question is
>> the same. For me, it's in the same repository and shipped with the package
>> source. I think that if you ship source (even via Hackage), you should also
>> ship tests. So, if somebody wants to modify the source, they can run the
>> tests. And making it convenient to test is very important, so I have "cabal
>> test" (or "runhaskell Setup.hs test" without cabal-install) configured to
>> run the tests. I don't think tests should (in general) be part of the
>> user-visible API, so I have them external to the module hierarchy.
> How do you set up cabal to do these tests?

I use the "runTests" hook in Distribution.Simple. The code below works on
Windows and Mac, because that's what we use.

module Main (main) where

import Distribution.Simple
import System.Cmd (system)
import System.FilePath ((</>))

main :: IO ()
main = defaultMainWithHooks hooks where
  hooks = simpleUserHooks { runTests = runTests' }

runTests' _ _ _ _ = system cmd >> return ()
  where testdir = "dist" </> "build" </> "test"
        testcmd = "." </> "test"
        cmd = "cd " ++ testdir ++ " && " ++ testcmd

Do your libraries depend on HUnit?

No, because I use an ultra-secret trick. ;) I have a Library in my .cabal
file and an Executable for testing. Part of the test description follows.

Executable test
  hs-source-dirs:       src, tests, examples
  main-is:              Main.hs

  -- Only enable the build-depends here if configured with "-ftest". This
  -- keeps users from having to install QuickCheck 2 in order to use EMGM.
  if flag(test)
    build-depends:      QuickCheck >= 2.0, HUnit >= 1.2
    buildable:          False

With that last flag-based if/else, I hide the dependencies for normal
building ('test' by default is False). If 'test' is False, then the
executable also cannot be built.

Where do you like to place your tests?  In the functionality modules?  A
> parallel structure?  A single Test.hs file somewhere?

In a separate "tests" directory at the same level as the "src" directory
containing the module hierarchy. It has a number of files, mostly one per
module tested.

> Testing non-exported functionality without exporting the test interface
>> seems difficult in general. Is there a way to hide part of a module
>> interface with Cabal? Then, you could have a 'test' function exported from
>> each module for testing but hidden for release.
> My current leaning is to split a package "foo" into packages "foo" and
>>> "foo-test"
>> What benefit does this provide?
> It keeps the library and its dependencies small.  Probably some of the
> alternatives do as well.  For testing, I'm using checkers<http://haskell.org/haskellwiki/Checkers>in addition to QuickCheck, and I'd prefer not to make casual library users
> have to pull in those libraries as well.

Ah, so you're handling the same problem we are in a different way. Nice!

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20080909/560c634e/attachment.htm

More information about the Haskell-Cafe mailing list