OUnit で OCaml コードの単体テストを書く
OUnit という単体テストフレームワークを使ってみます。XXXUnit と「大体あってる」二項関係をもつらしいです。
open OUnit let _ = run_test_tt_main ("test" >:: fun () -> assert_bool "should succeed" true)
assert_bool は (@?) としても定義されています。
open OUnit let _ = run_test_tt_main ("test" >:: fun () -> "should succeed" @? true)
比較します。
open OUnit let _ = run_test_tt_main ("test" >:: fun () -> assert_equal 0 0)
まあ普通ですね。"let (@=) = assert_equal" とかしておくといいかもしれないし、ダメかもしれない。
失敗させてみましょう。
open OUnit let _ = run_test_tt_main ("test" >:: fun () -> assert_equal 0 1)
じっこーします。
F
==============================================================================
Failure: testOUnit: not equal
- -
Ran: 1 tests in: 0.00 seconds.
FAILED: Cases: 1 Tried: 1 Errors: 0 Failures: 1 Skip:0 Todo:0
失敗してしまいました。悲しいですね…しかし何がどう間違ってたのか、値が出ないのは不親切ですね。悲しいです…
generic な print 関数がない言語なので当然でした。悲しみを乗り越えたら printer オプション引数で出力のために利用する関数を教えてあげます。
open Unit let _ = run_test_tt_main ("test" >:: fun () -> assert_equal ~printer:string_of_int 0 1)
えいやー
F
==============================================================================
Failure: hogeOUnit: expected: 0 but got: 1
- -
Ran: 1 tests in: 0.00 seconds.
FAILED: Cases: 1 Tried: 1 Errors: 0 Failures: 1 Skip:0 Todo:0
やりましたー。
値だけでてくれてもなんのこっちゃなので msg オプション引数で表示しましょう。
open Unit let _ = run_test_tt_main ("test" >:: fun () -> assert_equal ~msg:"hogehoge" ~printer:string_of_int 0 1)
F
==============================================================================
Failure: hogeOUnit: hogehoge
expected: 0 but got: 1
- -
Ran: 1 tests in: 0.00 seconds.
FAILED: Cases: 1 Tried: 1 Errors: 0 Failures: 1 Skip:0 Todo:0
極めてどうでもいいメッセージが表示されました。
テストっていうのはまあ複数あるものです。
open OUnit let _ = run_test_tt_main begin "tests" >::: [ "test 1" >:: begin fun() -> assert_equal 0 0 end; "test 2" >:: begin fun() -> assert_equal 0 0 end ] end
ヤヤ、それっぽい外見になりました!まあまじめに書くならこんな感じでしょう。
(>:::) で、テストのリストに名前をつけて、一つのテストにします。
あとはまあ set up, tear down でしょうか。
open OUnit let g = ref 0 let inc () = g := !g + 1 let set_up () = g := 0 let tear_down () = g := 0 let assert_g expected = assert_equal ~printer:string_of_int expected !g let test = let impl () = inc (); assert_g 1; inc (); assert_g 2 in "test" >:: bracket set_up impl tear_down let _ = run_test_tt_main ("tests" >::: [test; test])
例は適当です。そのまんま haskell の bracket です。ウルトラ微妙です…
まあそんなところです。あとは run_test_tt_main ですけど、これは勝手に引数のパースとかしてくれるえらい人で、-help で詳細が見れます。
usage: ./a.out [-verbose] [-only-test path]*
-verbose Run the test in verbose mode.
-only-test path Run only the selected test
-list-test List tests
-help Display this list of options
--help Display this list of options
オプション足したりもできるようです。まあこんなもんでしょう。おわり。