Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scalacheck: Generate list corresponding to list of generators

I want to generate a list of integers corresponding to a list of generators in ScalaCheck.

    import org.scalacheck._
    import Arbitrary.arbitrary

    val smallInt = Gen.choose(0,10)
    val bigInt = Gen.choose(1000, 1000000)
    val zeroOrOneInt = Gen.choose(0, 1)
    val smallEvenInt = smallInt suchThat (_ % 2 == 0)

    val gens = List(smallInt, bigInt, zeroOrOneInt, smallEvenInt)
    //val listGen: Gen[Int] = ??
    //println(listGen.sample) //should print something like List(2, 2000, 0, 6)

For the given gens, I would like to create a generator listGen whose valid sample can be List(2, 2000, 0, 6). Here is my first attempt using tuples.

    val gensTuple = (smallInt, bigInt, zeroOrOneInt, smallEvenInt)
    val tupleGen = for {
        a <- gensTuple._1
        b <- gensTuple._2
        c <- gensTuple._3
        d <- gensTuple._4
    } yield (a, b, c, d)

    println(tupleGen.sample) // prints Some((1,318091,0,6))

This works, but I don't want to use tuples since the list of generators(gens) is created dynamically and the size of the list is not fixed. Is there a way to do it with Lists?

I want the use the generator of the list(listGen) in scalacheck forAll property checking.

This looks like a toy problem but this is the best I could do to create a standalone snippet reproducing the actual issue I am facing.

like image 871
dips Avatar asked Nov 25 '12 07:11

dips


People also ask

Are there any built-in generators for ScalaCheck?

Built-in ScalaCheck generators Don’t forget that the org.scalacheck.Gen.scalaclass has many built-in generators. Here are function signatures and Scaladoc for many of them:

How to use the size parameter in a ScalaCheck generator?

When ScalaCheck uses a generator to generate a value, it feeds it with some parameters. One of the parameters the generator is given, is a size value, which some generators use to generate their values. If you want to use the size parameter in your own generator, you can use the Gen.sized method:

Is it possible to generate large ordered lists with ScalaCheck?

Here ScalaCheck tells us that the property hasn't been tested with any large and ordered list (which is no surprise, since the lists are randomised). Maybe we need to use a special generator that generates also large ordered lists, if that is important for testing our method thoroughly.

What types of data can be generated in ScalaCheck?

By default, ScalaCheck supports generation of List, Stream (Scala 2.10 - 2.12, deprecated in 2.13), LazyList (Scala 2.13), Set, Array, and ArrayList (from java.util ). You can add support for additional containers by adding implicit Buildable instances. See Buildable.scala for examples.


Video Answer


1 Answers

How about using the Gen.sequence method? It transforms an Iterable[Gen[T]] into a Gen[C[T]], where C can be List:

  def sequence[C[_],T](gs: Iterable[Gen[T]])(implicit b: Buildable[T,C]): Gen[C[T]] = 
     ...
like image 190
Eric Avatar answered Oct 12 '22 10:10

Eric