Code Examples for

ScalaCheck: The Definitive Guide

Return to chapter index

5 Properties in Detail

  • 5.1 Investigating property failures
  • 5.2 ScalaCheck's property combinators
  • 5.3 Conclusion
  • 5.1 Investigating property failures


    import org.scalacheck.Prop.{forAll, BooleanOperators} val p = forAll { xs: List[Int] => forAll { n: Int => (n >= 0 && n < xs.length) ==> xs(n) >= 0 } }
    scala> p.check ! Falsified after 0 passed tests. > ARG_0: List("-14386367") > ARG_0_ORIGINAL: List("1800647208", "-493891772") > ARG_1: 0
    import org.scalacheck.Prop.forAll import org.scalacheck.Gen.{oneOf, choose} val p = forAll(choose(0,100) :| "pos", choose(-10,0) :| "neg")(_ * _ < 0) val q = forAll('prime |: oneOf(2,3,5,7)) { prime => prime % 2 != 0 }
    scala> p.check ! Falsified after 19 passed tests. > pos: 0 > neg: 0 > neg_ORIGINAL: -84 scala> q.check ! Falsified after 7 passed tests. > prime: 2
    import org.scalacheck.Prop.{AnyOperators, forAll} def interleave[T](xs: List[T], ys: List[T]): List[T] = { if(xs.isEmpty) ys else if(ys.isEmpty) xs else xs.head :: ys.head :: interleave(xs.tail,xs.tail) } val propInterleave = forAll { (xs: List[Int], ys: List[Int]) => val res = interleave(xs,ys) res.length ?= (xs.length + ys.length) }
    scala> propInterleave.check ! Falsified after 5 passed tests. > Labels of failing property: Expected 3 but got 2 > ARG_0: List("0") > ARG_0_ORIGINAL: List("2061986129") > ARG_1: List("0", "0") > ARG_1_ORIGINAL: List("-2045643334", "-635574522")
    import org.scalacheck.Prop.{AnyOperators, forAll, all} def interleave[T](xs: List[T], ys: List[T]): List[T] = { if(xs.isEmpty) ys else if(ys.isEmpty) xs else xs.head :: ys.head :: interleave(ys.tail, xs.tail) } val propInterleave = forAll { (xs: List[Int], ys: List[Int]) => val res = interleave(xs,ys) val is = (0 to math.min(xs.length, ys.length)-1).toList all( "length" |: xs.length+ys.length =? res.length, "zip xs" |: xs =? is.map(i => res(2*i)) ++ res.drop(2*ys.length), "zip ys" |: ys =? is.map(i => res(2*i+1)) ++ res.drop(2*xs.length) ) }
    scala> propInterleave.check ! Falsified after 6 passed tests. > Labels of failing property: Expected List("0", "0") but got List("0", "1") zip xs > ARG_0: List("0", "0") > ARG_0_ORIGINAL: List("1", "423082184") > ARG_1: List("0", "1") > ARG_1_ORIGINAL: List("1730012397", "941647908")
    val propInterleave = forAll { (xs: List[Int], ys: List[Int]) => val res = interleave(xs,ys) val is = (0 to Math.min(xs.length, ys.length)-1).toList all( "length" |: xs.length+ys.length =? res.length, "zip xs" |: xs =? is.map(i => res(2*i)) ++ res.drop(2*ys.length), "zip ys" |: ys =? is.map(i => res(2*i+1)) ++ res.drop(2*xs.length) ) :| ("res: "+res) }
    scala> propInterleave.check ! Falsified after 7 passed tests. > Labels of failing property: Expected List("0", "-1") but got List("0", "0") zip xs res: List(0, 0, 0, -1) > ARG_0: List("0", "-1") > ARG_0_ORIGINAL: List("-2044148153", "2147483647", "-1") > ARG_1: List("0", "0") > ARG_1_ORIGINAL: List("-2147483648", "1073458288", "3876387")
    import org.scalatest._ import Matchers._ import prop.PropertyChecks._ forAll { (l1: List[Int], l2: List[Int]) => val res = interleave(l1,l2) val is = (0 to Math.min(l1.length, l2.length)-1).toList l1.length + l2.length shouldEqual res.length l1 shouldEqual is.map(i => res(2*i)) ++ res.drop(2*l2.length) l2 shouldEqual is.map(i => res(2*i+1)) ++ res.drop(2*l1.length) }
    TestFailedException was thrown during property evaluation. Message: List(0, 0) did not equal List(0, 1) Location: (<console>:23) Occurred when passed generated values ( arg0 = List(0, 0), // 3 shrinks arg1 = List(0, 1) // 33 shrinks )
    import org.scalacheck.Prop.{forAll, classify} val p = forAll { n:Int => classify(n % 2 == 0, "even", "odd") { classify(n < 0, "neg", "pos") { classify(math.abs(n) > 50, "large") { n+n == 2*n } } } }
    scala> p.check + OK, passed 100 tests. > Collected test data: 26% pos, even 20% neg, odd 18% pos, odd 12% neg, even 12% large, pos, odd 7% large, neg, even 3% large, neg, odd 2% large, pos, even
    import org.scalacheck.Prop.{forAll, collect} import org.scalacheck.Gen.choose val propSlice = forAll { xs: List[Int] => forAll(choose(0,xs.length-1)) { n => forAll(choose(n,xs.length)) { m => val slice = xs.slice(n,m) val label = slice.length match { case 0 => "none" case 1 => "one" case n if n == xs.length => "whole" case _ => "part" } collect(label) { xs.containsSlice(slice) } } } }
    scala> propSlice.check + OK, passed 100 tests. > Collected test data: 69% part 21% one 10% none
    l.containsSlice(slice) && l.containsSlice(l)

    5.2 ScalaCheck's property combinators


    import org.scalacheck.Prop.forAll import org.scalacheck.Gen.{choose, numChar, alphaChar} val p1 = forAll { n:Int => 2*n == n+n } val p2 = forAll { (s1:String, s2:String) => (s1+s2).endsWith(s2) } val p3 = forAll(choose(0,10)) { n => n >= 0 && n <= 10 } val p4 = forAll(numChar, alphaChar) { (cn,ca) => cn != ca }
    import org.scalacheck.Prop.{forAll, throws, classify} val propDivByZero = forAll { n:Int => throws(classOf[ArithmeticException]) (n/0) } val propListBounds = forAll { (xs: List[String], i: Int) => val inside = i >= 0 && i < xs.length classify(inside, "inside", "outside") { inside || throws(classOf[IndexOutOfBoundsException])(xs(i)) } }
    scala> propDivByZero.check + OK, passed 100 tests. scala> propListBounds.check + OK, passed 100 tests. > Collected test data: 84% outside 16% inside
    import org.scalacheck.Prop.exists import org.scalacheck.Gen.choose val p1 = exists { n:Int => (n % 2 == 0) && (n % 3 == 0) } val p2 = exists(choose(0,10)) { _ == 3 }
    scala> p1.check + OK, proved property. > ARG_0: 0 scala> p2.check + OK, proved property. > ARG_0: 3
    import org.scalacheck.Properties import org.scalacheck.Prop.{ undecided, proved, passed, exception, falsified } object ConstantProps extends Properties("Const") { property("p1") = undecided property("p2") = falsified property("p3") = proved property("p4") = passed property("p5") = exception(new Throwable("My fault")) }
    scala> ConstantProps.check ! Const.p1: Gave up after only 0 passed tests. 101 tests were discarded. ! Const.p2: Falsified after 0 passed tests. + Const.p3: OK, proved property. + Const.p4: OK, passed 100 tests. ! Const.p5: Exception raised on property evaluation. > Exception: java.lang.Throwable: My fault $line3.$read$$iw$$iw$ConstantProps$.<init>(<c... $line3.$read$$iw$$iw$ConstantProps$.<clinit>(...
    import org.scalacheck.Prop.{propBoolean, forAll} val propSorted = forAll { xs: List[Int] => val r = xs.sorted val isSorted = r.indices.tail.forall(i => r(i) >= r(i-1)) val containsAll = xs.forall(r.contains) val correctSize = xs.size == r.size isSorted :| "sorted" && containsAll :| "all elements" && correctSize :| "size" }

    5.3 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.