HUnit の使い方

近頃は仕事で使うちっさいテキストフィルタを Haskell で書いたりすることがあるんだけど、ユニットテストの書き方がよく分からない。いや、HUnit モジュールの使い方は id:jmk さんが丁寧に解説して下さっているんだけど、モジュール定義の仕方とコンパイルの仕方がいまいち。プログラム本体が書いてあるファイルで Main モジュールと main アクションが定義してあって、テストが書いてあるファイルで Main モジュールと main が定義してあったら、うまくコンパイルできないよなぁ…?

それとも main は Main の中になくてもいいんだっけ?

module Tested where

import System

hello :: String -> String
hello name = "Hello, " ++ name ++ "."

main :: IO ()
main = do args <- getArgs
          putStrLn (hello (args !! 0))
$ ghc -o Tested Tested.hs
e:/ghc/ghc-6.6.1/libHSrts.a(Main.o)(.text+0x1b):Main.c: undefined reference to `__stginit_ZCMain'
e:/ghc/ghc-6.6.1/libHSrts.a(Main.o)(.text+0x3f):Main.c: undefined reference to `ZCMain_main_closure'
collect2: ld returned 1 exit status

なんか、ダメっぽいですねぇ。

1 つのファイルに複数の module が定義できたりとか?

module Tested where

hello :: String -> String
hello name = "Hello, " ++ name ++ "."

module Main where

import Tested
import System

main :: IO ()
main = do args <- getArgs
          putStrLn (hello (args !! 0))
$ ghc -o Tested Tested.hs

Tested.hs:6:0: parse error on input `module'

…むりか?

じゃ、やっぱりプログラムの Main を書いたファイルと、テストの Main を書いたファイル、それにテスト対象の関数を定義した module を書いたファイルの 3 つを用意しなきゃないんだろか。

module Main where

import Tested
import System

main :: IO ()
main = do args <- getArgs
          putStrLn (hello (args !! 0))
module Main where

import Tested
import Test.HUnit

baseTest = ["Hello, RiKuO?" ~=? (hello "RiKuO")]

testData = ["base" ~: baseTest]

main = runTestTT (test testData)
module Tested where

hello :: String -> String
hello name = "Hello, " ++ name ++ "."

これで、まぁ、コマンドも作れるし、テストもできる、…けど、なぁ。

うーんと、いいのか、これで。こういうもんか。

$ ghc --make hello
[2 of 2] Compiling Main             ( hello.hs, hello.o )
Linking hello.exe ...

$ ./hello RiKuO
Hello, RiKuO.
$ ghc --make Test
[2 of 2] Compiling Main             ( Test.hs, Test.o )
Linking Test.exe ...

$ ./Test
### Error in:   0:base:0
user error (HUnit:expected: "Hello, RiKuO?"
 but got: "Hello, RiKuO.")
Cases: 1  Tried: 1  Errors: 1  Failures: 0

ちなみにわざと期待値をいじってみたので、メッセージが出る。