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
ちなみにわざと期待値をいじってみたので、メッセージが出る。