开发者

Organizing Haskell Tests

开发者 https://www.devze.com 2023-02-04 12:05 出处:网络
So I\'m trying to follow the suggested structure of a Haskell 开发者_Python百科project, and I\'m having a couple problems organizing my tests.

So I'm trying to follow the suggested structure of a Haskell 开发者_Python百科project, and I'm having a couple problems organizing my tests.

For simplicity, let's start with:

src/Clue/Cards.hs # defines Clue.Cards module
testsuite/tests/Clue/Cards.hs # tests Clue.Cards module

For one, I'm not sure what to name the module in testsuite/tests/Clue/Cards.hs that contains the test code, and for another, I'm no sure how to compile my test code so that I can link to my source:

% ghc -c testsuite/tests/Clue/Cards.hs -L src
testsuite/tests/Clue/Cards.hs:5:0:
    Failed to load interface for `Clue.Cards':
      Use -v to see a list of the files searched for.


I use myself the approach taken by Snap Framework for their test-suites, which basically boils down to:

  1. Use a test-framework such as haskell-test-framework or HTF
  2. Name the modules containing tests by appending .Tests to the module-name containing the IUT, e.g.:

    module Clue.Cards where ... -- module containing IUT
    
    module Clue.Cards.Tests where ... -- module containing tests for IUT
    
  3. By using separate namespaces, you can put your tests in a separate source-folder tests/, you can then use a separate Cabal build-target (see also cabal test-build-target support in recent Cabal versions) for the test-suite which includes the additional source folder in its hs-source-dirs setting, e.g.:

    Executable clue
      hs-source-dirs: src
      ...
    
    Executable clue-testsuite
      hs-source-dirs: src tests
      ...
    

    This works, since there's no namespace collision between the modules in your IUT and the test-suite anymore.


Here's another way:

Each module's unit tests are defined as a hunit TestList at the end of the module, with some consistent naming scheme, such as "tests_Path_To_Module". I think this helps me write tests, since I don't have to search for another module far away in the source tree, nor keep two parallel file hierarchies in sync.

A module's test list also includes the tests of any sub-modules. Hunit's runTestTT runner is built in to the app, and accessible via a test command. This means a user can run the tests at any time without special setup. Or if you don't like shipping tests in the production app, use CPP and cabal flags to include them only in dev builds, or in a separate test runner executable.

There are also functional tests, one or more per file in the tests/ directory, run with shelltestrunner, and some dev-process-related tests based in the Makefile.


Personally I feel that an extra ./src/ directory doesn't make much sense for small Haskell projects. Of coarse there's source, I downloaded the source code.

Either way (with or without src), I'd suggest you refactor and have a Clue directory and a Test directory:

./Clue/Cards.hs   -- module Clue.Cards where ...
./Test/Cards.hs   -- module Test.Cards where ...

This allows GHCi + Test.Cards to see Clue.Cards without any extra args or using cabal. On that note, if you don't use cabal + flags for optionally building your test modules then you should look into it.

Another option, which I use in many of my projects, is to have:

./Some/Module/Hierarchy/File.hs
./tests/someTests.hs

And I cabal install the package then run the tests/someTests.hs stuff. I guess this would be annoying if my packages were particularly large and too a long time to install.


For completeness sake, it worth mentioning a very easy approach for small project through ghci -i. For example, in your case,

>ghci -isrc:testsuite
ghci>:l Clue.Cards
ghci>:l tests.Clue.Cards
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号