Skip to content

Instantly share code, notes, and snippets.

@etorreborre
Created March 29, 2012 00:55
Show Gist options
  • Save etorreborre/2231981 to your computer and use it in GitHub Desktop.
Save etorreborre/2231981 to your computer and use it in GitHub Desktop.
Using Scalaz to get the applicative syntax for ScalaCheck generators
import scalaz.Apply
import org.scalacheck.Gen
import org.scalacheck.Arbitrary._
/**
* Use this trait to get applicative syntax when building generators. This
* is especially useful when building generators for case classes.
*
*/
trait Data {
/**
* import scalaz.Scalaz._
* case class MyClass(a: A, b: B, c: C)
*
* val MyCaseClassGenerator: Gen[MyCaseClass] = (genA |@| genB |@| genC)(MyCaseClass)
*
*/
implicit def genIsApply: Apply[Gen] = new Apply[Gen] {
def ap[A, B](fa: => Gen[A])(f: => Gen[(A) => B]) = fa.map2(f)((v, function) => function(v))
def map[A, B](fa: Gen[A])(f: (A) => B) = fa map f
}
}
@etorreborre
Copy link
Author

That was supposed to be clear from the comment :-). Something like that:

import org.scalacheck.Gen
import org.scalacheck.Gen._

case class Person(name: String, age: Int)

val names: Gen[String] = alphaStr suchThat (!_.isEmpty)
val ages: Gen[Int] = choose(1, 120)

val persons: Gen[Person] = (names |@| ages)(Person)

Then, in specs2 you can write properties like:

  import org.scalacheck._
  import org.scalacheck.Prop._

  implicit def arbitraryPerson = Arbitrary(genPerson)

  // using an implicit Arbitrary
  "a person must always have a positive age" >> check { person: Person =>
    person.age must be_>=(0)
  }

  // using an explicit Generator
  "a person must always have a non-empty name" >> forAll(persons) { person: Person =>
    person.name must not be empty
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment