テスト駆動開発はもう定着していると思うのですが、振舞駆動開発(BDD)の方はやってみたことがなかったので、Scala勉強会@東北の場を借りてやってみました。
scala-tohokuは既に15回もやってます、おそるべし週1ペース。次回で今年最後なので、遊びにきてくださいね。
specsはgoogle codeにホストされていて、QuickStartとUserGuideを読めば、だいたい使えると思います。
BDDはざっくり言えば、「仕様書=動くテストコード」を目指しているものだと思います。TDDに比べて、書き方も出力も、より口語に近い文書にしていく感じ。
import org.specs._
object someSpec extends Specification("何かの仕様") {
"何かは" should {
"真であること" >> {
"some" must_==/ "SOME"
"other" must beEqualToIgnoringCase("Other")
}
}
}
と書けば、
> scalac -cp specs.jar someSpec.scala
> scala -cp specs.jar someSpec
Specification "何かの仕様"
何かは should
+ 真であること
Total for specification "何かの仕様":
Finished in 0 second, 27 ms
1 example, 2 expectations, 0 failure, 0 error
などと、テスト仕様書というよりは詳細設計書をイメージして書いてテストする(この例だとあんまり違いわからないけど)。
BDDの活用についてはさておいて、scalaの慣習でちょっと困るのが、implicit conversion(暗黙の変換)を多用してDSL化することが多いので、文法的には一見きれいに見えますが、きもい!(scaladocsとの対応が読みづらい)
そこで、implicit conversionさせないで、よりJavaっぽくに書いてみました。一回こんな感じで書いたらAPIを追いやすくなりました。
/*
* ImplicitConvertionしないでAPIを明記したコード
*/
import org.specs._
import org.specs.matcher._
import org.specs.specification._
object nonImplicitSomeSpec extends Specification {
//org.specs.specification.SpecificationStructure
val futsuu:SpecificationStructure = declare("nonImplicitSomeSpec");
//org.specs.specification.Sus
val futsuuSus:Sus = futsuu.specify("implicitしないテスト")
futsuuSus.should {
//org.specs.specification.Example
val kimokunai:Example = forExample("コードがきもくないこと")
kimokunai.in(
{
//org.specs.specification.Expectable
val str:StringExpectable[String] = theString("some")
str.must_==/("SOME")
//org.specs.specification.Expectation
val expect:Expectation[String] = new Expectation("other")
// Specification < Matchers < StringMatchers
val required:Matcher[String] = beEqualToIgnoringCase("Other")
expect.must( required )
// 他に AnyMatchers, NumericMatchers, XmlMatchers など、
// Matcher[T] を生成するメソッドが定義されている。
// org.specs.matcher.Matchers を参照
}
)
}// end of futsuuSus should
}// end of NonImplicitSomeSpec
本当はこんなところを調べなくても書けるようにするのがDSLなんでしょうけど、「入りにくい」と感じたらこうやって分解してみるとスッキリしますね。「コードがきもくないこと」は振舞じゃないからテストケースとしてはオカシイのでヨロシク。
コメントいっぱい挟んでることを差し置いても、scalaっぽいコードとは一目瞭然で違います。
scalaかこいいYO!
追:
というわけで見てのとおり、テストをかっこよく書けるので、Javaで書いたアプリをscala+specsでテストするのもアリだと思いました。
テストツールとしてScalaを使うってのも、Scalaの使い方として良いような気がする。