property based testing with scalacheck
Post on 04-Jun-2015
477 Views
Preview:
DESCRIPTION
TRANSCRIPT
val propMax = Prop.forAll { (x: Int, y: Int) => val z = math.max(x, y) (z == x || z == y) && (z >= x && z >= y)}
propMax.check + OK, passed 100 tests.
val propMax = Prop.forAll { (x: Int, y: Int) => val z = math.max(x, y) (z == x || z == y) && (z >= x && z >= y)}
propMax.check + OK, passed 100 tests.
∀
val propMax = Prop.forAll { (x: Int, y: Int) => val z = math.max(x, y) (z == x || z == y) && (z >= x && z >= y)}
propMax.check + OK, passed 100 tests.
∀
val propMax = Prop.forAll { (x: Int, y: Int) => val z = math.max(x, y) (z == x || z == y) && (z >= x && z >= y)}
propMax.check + OK, passed 100 tests.
∀
val propMax = Prop.forAll { (x: Int, y: Int) => val z = math.max(x, y) (z == x || z == y) && (z >= x && z >= y)}
propMax.check + OK, passed 100 tests.
∀
class Gen[+T] { def apply(prms: Gen.Params): Option[T] }
Gen.choose(0, 100).sample res0: Option[Int] = Some(89) Prop.forAll(Gen.choose(0, 100)) ( _ <= 100 ).check + OK, passed 100 tests.
scala> Gen. alphaChar fail nonEmptyContainerOf sequence alphaLowerChar freqTuple nonEmptyListOf size alphaNumChar frequency nonEmptyMap sized alphaStr identifier numChar someOf alphaUpperChar isInstanceOf numStr toString asInstanceOf listOf oneOf uuid choose listOf1 option value chooseNum listOfN parameterized wrap const lzy pick zip containerOf mapOf posNum containerOf1 mapOfN resize containerOfN negNum resultOf
Custom Generators
val personGenerator = for { name <- Gen.alphaStr age <- Gen.choose(0, 150) } yield Person(name, age)Prop.forAll(personGenerator :| "Person") { p => p.toString ?= s"Person(${p.name},${p.age})"} case class Person(name: String, age: Int)
for { s <- Arbitrary.arbitrary[String] index <- Gen.choose(0, s.length)} yield (s, index)
val even = Gen.posNum[Int].suchThat(_ % 2 == 0) val odd = Gen.posNum[Int].suchThat(_ % 2 == 1) val number = Gen.frequency((2, even), (4, odd), (1, 0))Prop.forAll(number) { i => val label = if (i == 0) "zero" else if (i % 2 == 0) "even" else "odd" Prop.collect(label)(true) }.check(1000)
+ OK, passed 1000 tests. > Collected test data: 57% odd 29% even 14% zero
val even = Gen.posNum[Int].suchThat(_ % 2 == 0) val odd = Gen.posNum[Int].suchThat(_ % 2 == 1) val number = Gen.frequency((2, even), (4, odd), (1, 0))Prop.forAll(number) { i => val label = if (i == 0) "zero" else if (i % 2 == 0) "even" else "odd" Prop.collect(label)(true) }.check(1000)
+ OK, passed 1000 tests. > Collected test data: 57% odd 29% even 14% zero
val even = Gen.posNum[Int].suchThat(_ % 2 == 0) val odd = Gen.posNum[Int].suchThat(_ % 2 == 1) val number = Gen.frequency((2, even), (4, odd), (1, 0))Prop.forAll(number) { i => val label = if (i == 0) "zero" else if (i % 2 == 0) "even" else "odd" Prop.collect(label)(true) }.check(1000)
+ OK, passed 1000 tests. > Collected test data: 57% odd 29% even 14% zero
sealed trait Coincase object Head extends Coincase object Tail extends Coin
val coin = Gen.oneOf(Head, Tail)
val coins = Gen.listOf(coin)
val threeCoins = Gen.listOfN(3, coin)
scala> coins.sample res1: Option[List[Coin]] = Some(List(Head, Tail, Head, Tail, …))
scala> threeCoins.sample res2: Option[List[Coin]] = Some(List(Head, Head, Tail))
Coin
Coin
Int,String… Int, String…
Prop.forAll { xs: List[Int] => xs.reverse.reverse == xs }
Prop.forAll { xs: List[Int] => xs.reverse.reverse == xs }
Prop.forAll { xs: List[Int] => xs.reverse.reverse == xs }
import org.scalacheck.Prop.BooleanOperators
Prop.forAll { x: Int => (x >= 0) ==> { val root = math.sqrt(x) math.round(root * root) == x }}
val p = Prop.forAll { n: Int => (n >= 0 && n % 2 == 0 && n % 3 == 0) ==> n >= 0 } scala> p.check ! Gave up after only 52 passed tests. 262 tests were discarded.
val p = Prop.forAll { n: Int => (n >= 0 && n % 2 == 0 && n % 3 == 0) ==> n >= 0 } scala> p.check ! Gave up after only 52 passed tests. 262 tests were discarded.
val genNum = Gen.choose(0, Int.MaxValue) .retryUntil(_ % 2 == 0) .retryUntil(_ % 3 == 0) val p = Prop.forAll(genNum) { x: Int => x >= 0 } scala> p.check + OK, passed 100 tests.
val p = Prop.forAll( Gen.choose(0, Int.MaxValue) :| "x", Gen.choose(0, Int.MaxValue) :| "y") { case (x, y) => add(x, y) >= x && add(x, y) >= y}
scala> p.check ! Falsified after 0 passed tests. > x: 195667048 > x_ORIGINAL: 1350546201 > y: 1951816600 > y_ORIGINAL: 2004457204
val p = Prop.forAll( Gen.choose(0, Int.MaxValue) :| "x", Gen.choose(0, Int.MaxValue) :| "y") { case (x, y) => add(x, y) >= x && add(x, y) >= y}
scala> p.check ! Falsified after 0 passed tests. > x: 195667048 > x_ORIGINAL: 1350546201 > y: 1951816600 > y_ORIGINAL: 2004457204
195667048 + 1951816600 == Int.MaxValue + 1
val p = Prop.forAll( Gen.choose(0, Int.MaxValue) :| "x", Gen.choose(0, Int.MaxValue) :| "y") { case (x, y) => add(x, y) >= x && add(x, y) >= y}
scala> p.check ! Falsified after 0 passed tests. > x: 195667048 > x_ORIGINAL: 1350546201 > y: 1951816600 > y_ORIGINAL: 2004457204
195667048 + 1951816600 == Int.MaxValue + 1
val genListPosNum = Gen.listOf(Gen.choose(1, Int.MaxValue))val p = Prop.forAll(genListPosNum :| "positive numbers") { xs: List[Int] => xs.sorted.foldLeft(Option(0)) { case (mp, x) => mp.flatMap(p => if (p < x) Some(x) else None) }.isDefined}
scala> p.check ! Falsified after 6 passed tests. > positive numbers: List("1", "1") > positive numbers_ORIGINAL: List("1901315974", "963110019", "991102462")
val genListPosNum = Gen.listOf(Gen.choose(1, Int.MaxValue))val p = Prop.forAll(genListPosNum :| "positive numbers") { xs: List[Int] => xs.sorted.foldLeft(Option(0)) { case (mp, x) => mp.flatMap(p => if (p < x) Some(x) else None) }.isDefined}
scala> p.check ! Falsified after 6 passed tests. > positive numbers: List("1", "1") > positive numbers_ORIGINAL: List("1901315974", "963110019", "991102462")
val genListPosNum = Gen.listOf(Gen.choose(1, Int.MaxValue))val p = Prop.forAll(genListPosNum :| "positive numbers") { xs: List[Int] => xs.sorted.foldLeft(Option(0)) { case (mp, x) => mp.flatMap(p => if (p < x) Some(x) else None) }.isDefined}
scala> p.check ! Falsified after 6 passed tests. > positive numbers: List("1", "1") > positive numbers_ORIGINAL: List("1901315974", "963110019", "991102462")
class SampleTest extends Specification with ScalaCheck {
"Integer" should { "have a max method" in { Prop.forAll { (x: Int, y: Int) => val z = math.max(x, y) (z == x || z == y) && (z >= x && z >= y) } }
}
trait Monoid[A] { def op(a1: A, a2: A): A def zero: A object Laws { import scalaio.scalacheck.Eq import Eq._ def monoidIsAssociative(in: Gen[(A, A, A)])(implicit eq: Eq[A]): Prop = Prop.forAll(in) { case (x, y, z) => op(op(x, y), z) === op(x, op(y, z)) } def monoidHaveZero(in: Gen[A])(implicit eq: Eq[A]): Prop = Prop.forAll(in) { a => (op(a, zero) === a) && (op(zero, a) === a)} }}
val stringMonoid = new Monoid[String] { override def zero = "" override def op(a1: String, a2: String) = a1 + a2} def listMonoid[A] = new Monoid[List[A]] { override def op(a1: List[A], a2: List[A]) = a1 ++ a2 override def zero = List.empty[A] } val intAdditionMonoid = new Monoid[Int] { override def op(a1: Int, a2: Int) = a1 + a2 override def zero = 0 } val intMultiplicationMonoid = new Monoid[Int] { override def op(a1: Int, a2: Int) = a1 * a2 override def zero = 1 }
def endoMonoid[A] = new Monoid[A => A] { override def op(a1: A => A, a2: A => A) = { a: A => a1(a2(a)) } override def zero = identity}
def productMonoid[A, B](a: Monoid[A], b: Monoid[B]): Monoid[(A, B)] = new Monoid[(A, B)] { override def op(a1: (A, B), a2: (A, B)) = (a.op(a1._1, a2._1), b.op(a1._2, a2._2)) override def zero = (a.zero, b.zero)} def mapMergeMonoid[K, V](V: Monoid[V]): Monoid[Map[K, V]] = new Monoid[Map[K, V]] { override def op(a1: Map[K, V], a2: Map[K, V]) = a1.map { case (k, v) => (k, V.op(v, a2.get(k) getOrElse V.zero)) } override def zero = Map()}
def parReduce[A](as: List[A]) (implicit M: Monoid[A]): A = ???
def parMapReduce[A, B](as: List[A], f: A => B) (implicit M: Monoid[B]): B = ???
"String Monoid" should { "be associative" in { val genTriple = arbitrary[(String, String, String)] Monoids.stringMonoid.Laws.monoidIsAssociative(genTriple) } "have a zero" in { Monoids.stringMonoid.Laws.monoidHaveZero(arbitrary[String]) }}
trait Eq[A] { def equals(a1: A, a2: A): Prop} object Eq { implicit def orderedEq[A: Ordering]: Eq[A] = new Eq[A] { override def equals(a1: A, a2: A) = implicitly[Ordering[A]].equiv(a1, a2) } implicit def functionEq[A: Arbitrary, B]: Eq[A => B] = new Eq[A => B] { override def equals(f1: (A) => B, f2: (A) => B) = Prop.forAll(arbitrary[A]) { a => f1(a) == f2(a) } } implicit def listEq[A]: Eq[List[A]] = new Eq[List[A]] { override def equals(a1: List[A], a2: List[A]) = a1 == a2 } implicit class EqOps[A: Eq](a1: A) { def ===(a2: A): Prop = implicitly[Eq[A]].equals(a1, a2) }}
Functional Programming in ScalaPaul Chiusano and Rúnar Bjarnason
Manning
ScalaCheckThe Definitive Guide
Richard Nilsonartima
top related