What is it, naokirin?

OUnitで遊ぶ

OUnitはOCamlでは関数がオーバーロード出来ないとかそういう関係で複雑な処理に対してや、パラメタライズドなテストコードが非常にコード自体が見にくくなる傾向にあります。なので遊びがてらいろいろ試してみようと思いました。

open OUnit
open List

let (|>) x f = f x
let given f = f
let it msg f g x y = f g x y msg; y
let should f g x msg = f g x msg
let should_not f g x msg = f (fun n -> not (g n)) x msg
let be f g msg = assert_bool msg (f (g ()))
let equal x f msg = assert_equal x (f ()) ~msg:msg
let throw e f msg = assert_raises e f ~msg:msg
let verify f = ()

let test = "List" >::: [
  ".tl [1;2;3;4;5] is" >:: (fun () ->
    (fun () -> tl [1; 2; 3; 4; 5])
    |> it "no containing 1" should_not be (exists (fun i -> i=1))
    |> it "containing 2" should be (exists (fun i -> i=2))
    |> it "containing 3" should be (exists (fun i -> i=3))
    |> it "containing 4" should be (exists (fun i -> i=4))
    |> it "containing 5" should be (exists (fun i -> i=5))
    |> it "to be [2;3;4;5]" should equal [2; 3; 4; 5]
    |> verify);

  ".tl [] is" >:: (fun () ->
    (fun () -> tl [])
    |> it "throwing Failure" should throw (Failure "tl")
    |> verify);

  ".hd [1;2;3] is" >:: (fun () ->
    (fun () -> hd [1;2;3])
    |> it "to be 1" should equal 1
    |> verify)
]

let () = ignore (run_test_tt test)

反省はしている、だが後悔はしていない。
見たら分かる通り、NaturalSpecっぽく書けるようになるかなと思っていろいろ試してみた結果です。
NaturalSpecはもっと関数が多数定義されているのですが、今回はそういうのは抜きで(試験的に作れるか試すために)作ってみました。
見た目通り、この方向性では正直拡張性に乏しく、引数が煩雑なのでまず使えません。作るときにはあんまり見た目とか読みやすさとかは考慮してないというのもあります。(fun () -> (fun () -> ...) ...) とか正直あまりイケてないです。


ただOUnitはそもそもシンプルなテストを行う分にはコードの書き方さえ気をつけていれば、テストコード自体も言うほどひどくもないので拡張したいと思ったとしてもちょっとした拡張で十分だと思っています。なので、こんなことをするよりは、まだ自分のテストコードの書き方を改善する方が良い気がしますが…