概要
ScalaCheckのGen
は、プロパティベーステストで使用するテストデータを生成するためのジェネレーターです。
この記事では、Genの様々なメソッドを呼び出した結果について共有します。
const
Gen#const
は、引数で指定した値を生成するジェネレータを返します。
scala> Gen.const(1).sample
val res0: Option[Int] = Some(1)
choose
Gen#choose[T]
は、第一引数min
および第二引数max
で閉区間を指定して、
T
型の値をランダムに生成するジェネレータを返します。
scala> Gen.choose(0, 10).sample
val res4: Option[Int] = Some(10)
scala> Gen.choose(0, 10).sample
val res8: Option[Int] = Some(2)
scala> Gen.choose(0, 10).sample
val res9: Option[Int] = Some(6)
scala> Gen.choose(0, 10).sample
val res10: Option[Int] = Some(9)
scala> Gen.choose(0, 10).sample
val res11: Option[Int] = Some(0)
fail
Gen#fail
は、値を絶対に生成しないジェネレータを返します。
scala> Gen.fail.sample
val res2: Option[Nothing] = None
scala> Gen.fail[Int].sample
val res3: Option[Int] = None
個人的に捻り出したGen#fail
の使い道ですが、
以下のように無効なケースを明示的に扱う場合に使えるかもしれないです。
(他に何かいい使い方があれば教えてくださいm(_ _)m)
import org.scalacheck.Prop.forAll
import org.scalacheck.Gen
val validGen: Gen[Int] = Gen.choose(0, 10)
val invalidGen: Gen[Int] = Gen.fail // 0から10までの数字以外はインプットとして想定しないことを強調する
val prop = forAll(Gen.oneOf(validGen, invalidGen)) { n =>
n >= 0 && n <= 10
}
prop.check()
sequence
Gen#sequence
は、複数のジェネレータを組み合わせて、
それらのジェネレータが生成する値のコレクション(リスト、配列など)を生成するための関数です。
scala> Gen.sequence(List(org.scalacheck.Gen.alphaStr)).sample
val res27: Option[java.util.ArrayList[String]] = Some([ijdWdpIQdxGkKYINKJQ])
scala> import org.scalacheck.Gen.{alphaUpperStr, hexStr}
scala> Gen.sequence(Seq(alphaUpperStr, hexStr)).sample
val res30: Option[java.util.ArrayList[String]] = Some([PJBQKOMHSVFPHPIIVJXOKWPUGHSPLSQDJEFCKC, 76dB30803c6D6C3803404D9Ae44B4B45898B14B6cEce06d2A08Fa42b9c7C233c52B8ec28])
oneOf
Gen.oneOf
は、引数として与えられたジェネレータの中からランダムに1つを選び、
そのジェネレータを使って値を生成するジェネレータを返します。
scala> Gen.oneOf(1, 10, 100).sample
val res33: Option[Int] = Some(1)
scala> Gen.oneOf(1, 10, 100).sample
val res34: Option[Int] = Some(100)
scala> Gen.oneOf(Gen.const(1), Gen.const(2)).sample
val res1: Option[Int] = Some(1)
option
Gen.option
は、オプション型の値を生成するためのジェネレータを返します。
scala> Gen.option(1).sample
val res35: Option[Option[Int]] = Some(None)
scala> Gen.option(1).sample
val res36: Option[Option[Int]] = Some(Some(1))
either
Gen.either
は、Either型の値を生成するためのジェネレータを返します。
scala> Gen.either(100, "aaa").sample
val res41: Option[Either[Int, String]] = Some(Left(100))
scala> Gen.either(100, "aaa").sample
val res42: Option[Either[Int, String]] = Some(Right(aaa))
frequency
Gen.frequency
は、複数のジェネレータとその生成確率をペアにしたリストを受け取り、
指定された確率に従ってジェネレータを選択し、値を生成するジェネレータ返します。
scala> Gen.frequency(
| (20, Gen.const(20)),
| (80, Gen.const(80))
| ).sample
val res44: Option[Int] = Some(80)
scala> Gen.frequency(
| (20, Gen.const(20)),
| (80, Gen.const(80))
| ).sample
val res45: Option[Int] = Some(80)
scala> Gen.frequency(
| (20, Gen.const(20)),
| (80, Gen.const(80))
| ).sample
val res46: Option[Int] = Some(80)
scala> Gen.frequency(
| (20, Gen.const(20)),
| (80, Gen.const(80))
| ).sample
val res47: Option[Int] = Some(80)
scala> Gen.frequency(
| (20, Gen.const(20)),
| (80, Gen.const(80))
| ).sample
val res48: Option[Int] = Some(20)
listOf
Gen#listOf
は、指定されたジェネレータを使って要素を生成し、それらの要素からなるリストを生成するジェネレータを返します。
scala> Gen.listOf(Gen.const(1)).sample
val res2: Option[List[Int]] = Some(List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1))
scala> Gen.listOf(
| Gen.frequency(
| (20, Gen.const(20)),
| (80, Gen.const(80))
| )
| ).sample
val res4: Option[List[Int]] = Some(List(80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 20, 80, 20, 20, 80, 20, 20, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 20, 80, 20, 80, 80, 80, 80, 20, 20, 20, 80, 80, 20, 80))
scala> res4.get.filter(_ == 20).size.toDouble / res4.get.size
val res6: Double = 0.22916666666666666
listOfN
Gen#listOfN
は、Gen#listOf
とほぼ同じですが、生成するリストの長さを引数で指定できます。
scala> Gen.listOfN(3, Gen.const(1)).sample
val res7: Option[List[Int]] = Some(List(1, 1, 1))