[Haskell-cafe] Organizaing tests in Haskell

Matthew West haskell-cafe at matthewwest.co.uk
Sun Sep 23 12:16:46 CEST 2012

On 23 Sep 2012, at 10:25, Jan Stolarek wrote:

> Dear list,
> during many years of Java programming I've been faithful to TDD methology. Recently I've been 
> trying to figure out how to do tests in Haskell. Thanks to RWH and help from great folks at 
> #haskell I've managed to get on my feet. There is however one issue I wasn't able to solve.
> In Java it is very easy to separate test code from the actual source. A Java project simply 
> contains two folders: src and tests. These two are treated as the source directories. Both these 
> directories have the same subdirectory structure. For example I have a source file 
> src/myPackage/mySubpackage/MyClass.java and test for it are kept in file 
> tests/myPackage/mySubpackage/MyClassTest.java. These two files are considered by Java to be in 
> the same package. Here's the main trick: fileds and methods that are marked as protected in Java 
> are accessible to other classes in the same package. This allows to test internal methods of a 
> class by marking them as protected instead of private. This breaks encapsulation but only within 
> a package, which is acceptable.
> Now I'd like to achieve something similar in Haskell. I'm using cabal's support for testing. I 
> created separate src and tests directories, both with the same subdirectory structure. I keep 
> tests for each module in a separate file (e.g. I have src/Math/MyModule.hs and 
> tests/Math/MyModuleTest.hs) and I have one file that assembles all the tests into a single test 
> suite (I use test-framework for that). The only problem is that in order to test some function 
> from a module I have to expose that function, which pretty much forces me to give up on 
> encapsulation.
> Is there any better solution to organize tests in Haskell? Should I just give up on module 
> encapsulation, or should I only test functions exposed by the module and don't worry about 
> internal functions? Perhaps I should use some different approach?
> Jan
  From looking at other packages on Hackage a common trick seems to be to create some internal modules, 
then have an external module that simply exposes the 'public' functions.  Your internal tests can then import 
the internal modules, and your API tests can import the external module.  Of course others are still able to import 
your Internal modules, but you have at least made it clear that that is a bad idea.

for example:


module MyLib.Internal.Lib where -- exports all the functions defined in this function
internalFunction = ...
externalFunction = ...

module MyLib.Lib (       -- exports only the public functions
import MyLib.Internal.Lib  -- imports all the internal functions

import MyLib.Internal.Lib

import MyLib.Lib   -- imports only the public API

Yesod is an example of a large project using this approach, for example https://github.com/yesodweb/yesod/tree/master/yesod-core


> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe

More information about the Haskell-Cafe mailing list