Specsでテストケースを書いてみる

SpecsはScalaのBDD用ライブラリです。BDDスタイルでテストケースを記述するための機能に加えてMockitoなどのモックライブラリと連携するための機能を備えているのが特徴です。

試しにこんなメソッドのテストケースを書いてみます。

object Util {
  def url(value: String) : String = URLEncoder.encode(value, "UTF-8")
}

テストケース(スペックと呼ぶべき?)はこんな感じ。mustEqualの他にもorg.specs.Expectationsで定義されているアサート用のメソッドを使用して結果の検証を行うことができます。例外を投げられるかどうかもtry-catchを記述せずに確認できます。

import org.specs._

object UtilTestSpec extends Specification {
  "url()" should {
    "encode as UTF-8" in {
      Util.url("こんにちは") mustEqual 
        "%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF"
    }
    "throw NullPointerException for null" in {
      Util.urlEncode(null) must throwA(new NullPointerException())
    }  
  }
}

テストの実行結果(すべて成功した場合)は以下のようになります。スペックがグループ化されて表示されます。通常はテスト対象のメソッド単位でグループ化しておくとよいでしょう。どのメソッドがどのような仕様に基づいてテストされているのか、また、どの仕様に対するテストが失敗しているのかが一目瞭然です。

[info] == code.util.UtilTestSpec ==
[info] + url() should
[info]   + encode as UTF-8
[info]   + throw NullPointerException for null
[info] == code.util.UtilTestSpec ==

BDDというと敷居が高い気がしますが、「仕様を明確にするためのドキュメントを兼ねたテストケース」と考えてJUnitの代わりに使うのであれば、少なくともJUnitでテストケースを書ける人であればSpecsのテストケースも問題なく記述することができるのではないでしょうか。
JavaでもBDD用のライブラリは存在しますが、Javaコードではなく独自のスクリプトでテストケースを記述する必要があるなど、構文に柔軟性がないためBDD用のDSLというところまではなかなかいきません。なので、JavaクラスのテストケースをSpecsで記述するというのもよいかもしれません。