NaturalSpec+unquoteで出力をリッチにしようとしたけど現実は厳しかった

TDD Advent Calendarの没ネタその9。先月やってみようと思っていて忘れていた一品(昨日思い出した)。

PowerAssertあるよね

Groovyのあれ。あれいいよね見やすくて。

F# でも似たようなものがあるよ

その名もunquote。本家サイトトップページの一番下に"Unquote was inspired by Groovy Power Asserts"と記述されている。

unquote - Write F# unit test assertions as quoted expressions, get step-by-step failure messages for free - Google Project Hosting

ちょっと仕組みについては割愛させていただく。
きちんと更新されているみたいだし(.NET4.5に対応できているかしらないが)、使ってみない手はないでしょー。

まぁ、本家サイトにも書かれている通りNUnitやMSTest、あとFsUnitなら普通に動く。そんなにいじるわけでもないのでそりゃそうだ、という感じ。

NaturalSpecでやりたい

NaturalSpecはGiven,When,It shouldなんちゃらなどの関数を使うため、そのままではunquoteの関数は使えない。いや、GivenWhenを使わなければ使えるのだけど、それではNaturalSpecの意味がなくなるので。。。
というわけでNaturalSpecのUtil.fsやらSyntax.fsに存在する関数のうちいくつかを上書きしてみた。

そしてテストコードを書いた結果がこれ。

[<Scenario>]
let ``とりあえず割り算のテスト``() =
  Given (1,1)
  ||> When (fun x y -> <@ x / y @>) // うにょーん
  |> It should equal 2
  |> Verify

[<Scenario>]
let ``リスト操作のテスト``() =
  Given [1;2;3;4;5]
  |> When removing 3 // removingはシャドウィングでコードクォート用のものを作った
  |> It shouldn't contain 3
  |> It should contain 4
  |> It should have (length 3)
  |> It shouldn't have duplicates
  |> Verify

ラムダ式…これはきつい。コードクォート内に式を書かなければならないので仕方のないことだが、それでも全テストにラムダ式はきつい。ラッパー関数を作るにしても、数が多ければきつい。私は悲しい。
テスト結果はこちら。

UnquoteSpec.とりあえず割り算のテスト:

Elements are not equal.
1 / 1 = 2
1 = 2
false

UnquoteSpec.リスト操作のテスト:
(Seq.filter (fun y -> 3 <> y) [1; 2; 3; 4; 5] |> Seq.length) = 3
(seq [1; 2; 4; 5] |> Seq.length) = 3
4 = 3
false

通常のものよりはかなり見やすい気がする。そして、出力に関してはこちらでいじれるのでもっおなんとかできる気がする。気がするのだが・・・やはりテストコード側がネックだ。


というわけでF# erのどなたが素晴らしい改造を施してくださることを祈りつつ、私はunquoteを使う場合はFsUnitにしようと妥協するのだった。

ソース

見るからにNaturalSpecのコードをラッパーしたとしかいえないですね。