arbitrary
GeneratorThere is a special generator, org.scalacheck.Arbitrary.arbitrary
, which generates arbitrary values of any
supported type.
val evenInteger = Arbitrary.arbitrary[Int] suchThat (_ % 2 == 0)
val squares = for {
xs <- Arbitrary.arbitrary[List[Int]]
} yield xs.map(x => x * x)
The arbitrary
generator is the generator used by ScalaCheck when it generates values for property parameters.
Most of the times, you have to supply the type of the value to arbitrary
, like above, since Scala often can't
infer the type automatically. You can use arbitrary
for any type that has an implicit Arbitrary
instance.
As mentioned earlier, ScalaCheck has default support for common types, but it is also possible to define your own
implicit Arbitrary
instances for unsupported types. See the following implicit Arbitrary definition for booleans,
that comes from the ScalaCheck implementation.
implicit lazy val arbBool: Arbitrary[Boolean] = Arbitrary(oneOf(true, false))
Let's see an example where we're defining an implicit
arbitrary
instance for Char
import org.scalacheck.Arbitrary
import org.scalacheck.Gen
import org.scalacheck.Prop.forAll
implicit lazy val myCharArbitrary = Arbitrary(Gen.oneOf('A', 'E', 'I', 'O', 'U'))
val validChars: Seq[Char] = res0
check(forAll { c: Char => validChars.contains(c) })
This becomes more useful when we're dealing with our own data types. We'll use the case class defined in the Generators Section:
case class Foo(intValue: Int, charValue: Char)
Having an implicit def
or val
of our data type in the scope allow us to use the forAll
method without
specifying the generator
import org.scalacheck.Arbitrary
import org.scalacheck.Gen
import org.scalacheck.Prop.forAll
val fooGen = for {
intValue <- Gen.posNum[Int]
charValue <- Gen.alphaChar
} yield Foo(intValue, charValue)
implicit lazy val myFooArbitrary = Arbitrary(fooGen)
check(forAll { foo: Foo => (foo.intValue < 0) == res0 && !foo.charValue.isDigit })
The Arbitrary.arbitrary
method also returns a Gen
object.
import org.scalacheck.Arbitrary
import org.scalacheck.Gen.listOfN
import org.scalacheck.Prop.forAll
val genEightBytes = listOfN(8, Arbitrary.arbitrary[Byte])
check(forAll(genEightBytes)(list => list.size == res0))