Code Examples for

ScalaCheck: The Definitive Guide

Return to chapter index

3 ScalaCheck Fundamentals

  • 3.1 The Prop and Properties classes
  • 3.2 Generators
  • 3.3 Test case simplification
  • 3.4 Conclusion
  • 3.1 The Prop and Properties classes


    import org.scalacheck.Prop val propStringLength = Prop.forAll { s: String => val len = s.length (s+s).length == len+len } val propDivByZero = Prop.throws(classOf[ArithmeticException]) { 1/0 } val propListIdxOutOfBounds = Prop.forAll { xs: List[Int] => Prop.throws(classOf[IndexOutOfBoundsException]) { xs(xs.length+1) } }
    import org.scalacheck.Properties import org.scalacheck.Prop.{forAll, throws} object MySpec extends Properties("MySpec") { property("list tail") = forAll { (x: Int, xs: List[Int]) => (x::xs).tail == xs } property("list head") = forAll { xs: List[Int] => if (xs.isEmpty) throws(classOf[NoSuchElementException]) { xs.head } else xs.head == xs(0) } }
    scala> MySpec.check + MySpec.list tail: OK, passed 100 tests. + MySpec.list head: OK, passed 100 tests.

    3.2 Generators


    class Gen[+T] { def apply(prms: Gen.Params): Option[T] }
    scala> import org.scalacheck.Gen import org.scalacheck.Gen scala> val myGen = Gen.choose(1,10) myGen: org.scalacheck.Gen[Int] = Gen() scala> myGen(Gen.Params()) res0: Option[Int] = Some(7) scala> myGen.sample res1: Option[Int] = Some(5)
    import org.scalacheck.Gen.choose val myGen = for { n <- choose(1, 50) m <- choose(n, 2*n) } yield (n, m)
    scala> myGen.sample res0: Option[(Int, Int)] = Some((45,60)) scala> myGen.sample res1: Option[(Int, Int)] = Some((29,37))
    trait Color case object Red extends Color case object Green extends Color trait Shape { def color: Color } case class Line(val color: Color) extends Shape case class Circle(val color: Color) extends Shape case class Box(val color: Color, val boxed: Shape) extends Shape
    import org.scalacheck.Gen val genColor = Gen.oneOf(Red, Green) val genLine = for { color <- genColor } yield Line(color) val genCircle = for { color <- genColor } yield Circle(color) val genBox = for { color <- genColor shape <- genShape } yield Box(color, shape) val genShape: Gen[Shape] = Gen.oneOf(genLine, genCircle, genBox)
    scala> genShape.sample res0: Option[Shape] = Some(Line(Green)) scala> genShape.sample res1: Option[Shape] = Some(Box(Blue,Box(Red,Circle(Green))))
    import org.scalacheck.{Gen, Prop} val evenInt = for { n <- Gen.choose(-1000, 1000) } yield 2*n val propDivide = Prop.forAll(evenInt) { n: Int => val half = n/2 n == 2*half }
    import org.scalacheck.Prop.forAll import org.scalacheck.Gen.{posNum, negNum} val p = forAll(posNum[Int], negNum[Int]) { (n,m) => n*m <= 0 }
    import org.scalacheck.Prop.forAll import org.scalacheck.Gen.choose val propPrefix = forAll { s: String => forAll(choose(0, s.length)) { n => val prefix = s.substring(0, n) s.startsWith(s) } }
    import org.scalacheck.Arbitrary.arbitrary import org.scalacheck.Gen.choose val genStringWithN = for { s <- arbitrary[String] n <- choose(0, s.length) } yield (s,n)
    import org.scalacheck.Prop.forAll val propPrefix = forAll(genStringWithN) { case (s,n) => val prefix = s.substring(0, n) s.startsWith(s) }
    import org.scalacheck.Gen.{choose, oneOf} case class Person ( firstName: String, lastName: String, age: Int ) { def isTeenager = age >= 13 && age <= 19 } val genPerson = for { firstName <- oneOf("Alan", "Ada", "Alonzo") lastName <- oneOf("Lovelace", "Turing", "Church") age <- choose(1,100) } yield Person(firstName, lastName, age)
    scala> import org.scalacheck.Arbitrary import org.scalacheck.Arbitrary scala> implicit val arbPerson = Arbitrary(genPerson) arbPerson: org.scalacheck.Arbitrary[Person] = org.scalacheck.Arbitrary$$anon$1@1391f61c
    scala> import org.scalacheck.Prop.forAll import org.scalacheck.Prop.forAll scala> val propPerson = forAll { p: Person => | p.isTeenager == (p.age >= 13 && p.age <= 19) | }

    3.3 Test case simplification


    import org.scalacheck.Prop.forAll import org.scalacheck.Gen.choose val propNoPairs = forAll { xs: List[Byte] => forAll(choose(0, xs.length-2)) { i => xs(i) != xs(i+1) } }
    scala> propNoPairs.check ! Falsified after 11 passed tests. > ARG_0: List("127", "127") > ARG_0_ORIGINAL: List("-104", "127", "127", "-1", "89") > ARG_1: 0

    3.4 Conclusion

    For more information about ScalaCheck: The Definitive Guide, please visit:

    http://www.artima.com/shop/scalacheck

    and:

    http://booksites.artima.com/scalacheck

    Copyright © 2013-2014 Artima, Inc. All rights reserved.

    Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.