Cabal でテストを走らせる

今のところ標準的な方法はないけど,@shelarcy さんによると GSoC のプロジェクトで Cabal の test 機能を改善している最中だそうです.
http://socghop.appspot.com/gsoc/student_project/show/google/gsoc2010/haskell/t127230760295
http://cabaltest.blogspot.com/


しかし現状の Cabal では自分で hook を書くしかなさそう.
具体的には

.
|-- LICENSE
|-- Setup.hs
|-- hayate.cabal
|-- src
|   |-- Device.hs
|   |-- Hayate.hs
|   `-- Main.hs
`-- test
    |-- test_device.hs
    `-- test_hayate.hs

2 directories, 8 files

こんなかんじのディレクトリ構成で,

Name: hayate
Version: 0.1
Synopsis: kawaii
License: BSD3
License-file: LICENSE
Author: eagletmt
Maintainer: eagletmt@example.com
Category: Character

Build-type: Custom

Cabal-version: >=1.2

Executable hayate
  Hs-source-dirs: src
  Main-is: Main.hs
  Build-depends: base

Executable test_device
  Hs-source-dirs: src, test
  Other-modules: Device
  Main-is: test_device.hs
  Build-depends: HUnit

Executable test_hayate
  Hs-source-dirs: src, test
  Other-modules: Hayate
  Main-is: test_hayate.hs
  Build-depends: HUnit

Build-type: Custom に注意してこんなかんじの cabal ファイルを書き,Setup.hs には

import Distribution.Simple
import Distribution.PackageDescription
import Distribution.Simple.LocalBuildInfo
import System.Process (system)
import System.FilePath ((</>))

main = defaultMainWithHooks hooks
  where
    hooks = simpleUserHooks { runTests = runTests' }

runTests' :: Args -> Bool -> PackageDescription -> LocalBuildInfo -> IO ()
runTests' _ _ _ lbi = mapM_ (\s -> putStrLn ("running " ++ s ++ "...") >> system (buildDir lbi </> s </> s)) tests
  where
    tests = ["test_device", "test_hayate"]

こんなのを書く.


するとこんなかんじにビルドを進めることができる.

% runghc Setup.hs configure --user
Configuring hayate-0.1...
% runghc Setup.hs build
Preprocessing executables for hayate-0.1...
Building hayate-0.1...
[1 of 3] Compiling Device           ( src/Device.hs, dist/build/hayate/hayate-tmp/Device.o )
[2 of 3] Compiling Hayate           ( src/Hayate.hs, dist/build/hayate/hayate-tmp/Hayate.o )
[3 of 3] Compiling Main             ( src/Main.hs, dist/build/hayate/hayate-tmp/Main.o )
Linking dist/build/hayate/hayate ...
[1 of 2] Compiling Device           ( src/Device.hs, dist/build/test_device/test_device-tmp/Device.o )
[2 of 2] Compiling Main             ( test/test_device.hs, dist/build/test_device/test_device-tmp/Main.o )
Linking dist/build/test_device/test_device ...
[1 of 3] Compiling Device           ( src/Device.hs, dist/build/test_hayate/test_hayate-tmp/Device.o )
[2 of 3] Compiling Hayate           ( src/Hayate.hs, dist/build/test_hayate/test_hayate-tmp/Hayate.o )
[3 of 3] Compiling Main             ( test/test_hayate.hs, dist/build/test_hayate/test_hayate-tmp/Main.o )
Linking dist/build/test_hayate/test_hayate ...
% runghc Setup.hs test
running test_device...
Cases: 1  Tried: 1  Errors: 0  Failures: 0
running test_hayate...
Cases: 1  Tried: 1  Errors: 0  Failures: 0