ScalaCheck を試す (3) カスタムジェネレータを作る [Scala]
間が空いてしまったけど ScalaCheck を試す続き。
たとえば「任意の整数について」という条件の代わりに「任意の偶数について」など、より限定的な条件を仕様の前提にしたいとする。ひとつの方法は [1] で言及したように ==> を使って前提条件を記述するやりかたがある。でもこの方法だと「任意の整数」を生成した後で前提条件による篩をかけるので無駄が多く、厳しい条件だといつまでたっても有効なテストデータが生成されないということがありうる。
このような場合はカスタムジェネレータを作って最初から有効なデータのみが生成されるようにする。任意の偶数を生成するジェネレータは以下のように書く。
val genEven: Gen[Int] = for (n <- arbitrary[Int]) yield n * 2
for comprehension のジェネレータの部分に ScalaCheck の既存のジェネレータを書くことが出来る。この構文を使ったのはうまいと思う。
ジェネレータを明示的に指定して性質を記述するには forAll を使う。
val propEven = forAll(genEven) (x => x % 2 == 0)
テストの実行はいつもどおり。
scala> check(propEven) +++ OK, passed 100 tests. res39: scalacheck.TestStats = TestStats(TestPassed(),100,0)
作成したカスタムジェネレータをその型のデフォルトのジェネレータにするには暗黙の型変換メソッドを書く。以下は Int のデフォルトジェネレータを偶数のみのジェネレータにしてしまう。
scala> check(property((x:Int) => x % 2 == 0)) *** Failed, after 1 successful tests: The arguments that caused the failure was: List(-1) res43: scalacheck.TestStats = TestStats(TestFailed(List(-1)),1,0) scala> implicit def arbitraryInt(x: Arbitrary[Int]) = genEven arbitraryInt: (scalacheck.Arbitrary[Int])scalacheck.Gen[Int] scala> check(property((x:Int) => x % 2 == 0)) +++ OK, passed 100 tests. res44: scalacheck.TestStats = TestStats(TestPassed(),100,0) scala> check(property((x:Int) => x % 2 == 0)) +++ OK, passed 100 tests. res45: scalacheck.TestStats = TestStats(TestPassed(),100,0)
[1] http://blog.so-net.ne.jp/rainyday/2007-08-08-1
コメント 0