Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sized generators in scalacheck

UserGuide of scalacheck project mentioned sized generators. The explanation code

def matrix[T](g:Gen[T]):Gen[Seq[Seq[T]]] = Gen.sized {size =>
 val side = scala.Math.sqrt(size).asInstanceOf[Int] //little change to prevent compile-time exception
 Gen.vectorOf(side, Gen.vectorOf(side, g))
}

explained nothing for me. After some exploration I understood that length of generated sequence does not depend on actual size of generator (there is resize method in Gen object that "Creates a resized version of a generator" according to javadoc (maybe that means something different?)).

val g =  Gen.choose(1,5)
val g2 = Gen.resize(15, g)
println(matrix(g).sample) //  (1)
println(matrix(g2).sample) // (2)
//1,2 produce Seq with same length 

Could you explain me what had I missed and give me some examples how you use them in testing code?

like image 983
Jeriho Avatar asked Sep 08 '10 10:09

Jeriho


1 Answers

The vectorOf (which now is replaced with listOf) generates lists with a size that depends (linearly) on the size parameter that ScalaCheck sets when it evaluates a generator. When ScalaCheck tests a property it will increase this size parameter for each test, resulting in properties that are tested with larger and larger lists (if listOf is used).

If you create a matrix generator by just using the listOf generator in a nested fashion, you will get matrices with a size that depends on the square of the size parameter. Hence when using such a generator in a property you might end up with very large matrices, since ScalaCheck increases the size parameter for each test run. However, if you use the resize generator combinator in the way it is done in the ScalaCheck User Guide, your final matrix size depend linearly on the size parameter, resulting in nicer performance when testing your properties.

You should really not have to use the resize generator combinator very often. If you need to generate lists that are bounded by some specific size, it's much better to do something like the example below instead, since there is no guarantee that the listOf/ containerOf generators really use the size parameter the way you expect.

def genBoundedList(maxSize: Int, g: Gen[T]): Gen[List[T]] = {
  Gen.choose(0, maxSize) flatMap { sz => Gen.listOfN(sz, g) }
}
like image 113
rickynils Avatar answered Sep 21 '22 11:09

rickynils