Chapter 9 QuickCheck Questions Momentum © 2015 Pearson Education, Inc.
QuickCheck ClojureCheck ScalaCheck - Meetup
Transcript of QuickCheck ClojureCheck ScalaCheck - Meetup
![Page 1: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/1.jpg)
QuickCheckClojureCheckScalaCheck
Dave Gurnell
Property-based testing with...
![Page 2: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/2.jpg)
Testing(it’s good ...but it’s time consuming)
![Page 3: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/3.jpg)
cost(maintenance) > cost(development)
![Page 4: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/4.jpg)
test("reverse an empty list") { assert(List().reverse === List())}
test("reverse a list of length 2") { assert(List("a", "b").reverse === List("b", "a"))}
test("reverse a list with a null in it") { assert(List("a", null).reverse === List(null, "a"))}
test("reverse a palindrome (?!)") { assert("TACOCAT".toList.reverse === "TACOCAT".toList)}
Lots of tests = lots of maintenance...
![Page 5: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/5.jpg)
How can we get similar coveragewith less code?
![Page 6: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/6.jpg)
Properties(aka “Invariants”)
![Page 7: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/7.jpg)
reverse(a ++ b) == reverse(b) ++ reverse(a)
reverse(reverse(a)) == a
endpoint(request).status != 500
i > 0 ==> i/2 < i
![Page 8: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/8.jpg)
∀a,b reverse(a ++ b) == reverse(b) ++ reverse(a)
∀a reverse(reverse(a)) == a
∀request endpoint(request).status != 500
i > 0 ==> i/2 < i∀i
Problem - these are all universally quantified...
![Page 9: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/9.jpg)
We can’t test all possible inputs to our properties.
Can we find a representative sample instead?
![Page 10: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/10.jpg)
Generators(define inputs to properties)
![Page 11: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/11.jpg)
import org.scalacheck.Gen
val ints = Gen.oneOf(1, 2, 3) // Gen[Int]
ints.sample // => Some(1)ints.sample // => Some(3)ints.sample // => Some(2)
Generators samples values from large datasets
![Page 12: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/12.jpg)
import org.scalacheck.Gen
val lists = Gen.listOf(Gen.oneOf(1, 2, 3))
lists.sample // => Some(List(1, 3, 2, ... lists.sample // => Some(List())lists.sample // => Some(List(2, 3, 3, ...
Generators samples values from large datasets
![Page 13: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/13.jpg)
import org.scalacheck.Genimport org.scalacheck.Prop.forAll
val lists = Gen.listOf(Gen.oneOf(1, 2, 3))
val prop = forAll(lists) { list => list.reverse.reverse == list}
Use generators to approximate universal quantification
![Page 14: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/14.jpg)
import org.scalacheck.Genimport org.scalacheck.Prop.forAll
val lists = Gen.listOf(Gen.oneOf(1, 2, 3))
val prop = forAll(lists) { list => list.reverse.reverse == list}
prop.check // stdout: OK, passed 100 tests.
Use generators to approximate universal quantification
![Page 15: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/15.jpg)
import org.scalacheck.Genimport org.scalacheck.Prop.forAll
val lists = Gen.listOf(Gen.oneOf(1, 2, 3))
val prop = forAll(lists, lists) { (a, b) => (a ++ b).reverse == b.reverse ++ a.reverse}
prop.check // stdout: OK, passed 100 tests.
Use generators to approximate universal quantification
![Page 16: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/16.jpg)
import org.scalacheck.Genimport org.scalacheck.Prop.forAll
val lists = Gen.listOf(Gen.oneOf(1, 2, 3))
val prop = forAll(lists, lists) { (a, b) => (a ++ b).reverse == a.reverse ++ b.reverse}
prop.check // stdout: Falsified after 2 tests. // ARG_0: List(0) // ARG_1: List(1)
Use generators to approximate universal quantification
![Page 17: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/17.jpg)
“Arbitraries”(materialize generators from types)
![Page 18: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/18.jpg)
import org.scalacheck.Arbitrary.arbitrary
val ints = arbitrary[Int] // Gen[Int]
ints.sample // => Some(2147483647)ints.sample // => Some(-1)
val lists = arbitrary[List[Int]] // Gen[List[Int]]
lists.sample // => Some(List(2120334425, 0, 0, ...lists.sample // => Some(List(-1639755040, 1, ...
![Page 19: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/19.jpg)
import org.scalacheck.Prop.forAll
forAll { (a: List[Int]) => a.reverse.reverse == a}
forAll { (a: List[Int], b: List[Int]) => (a ++ b).reverse == b.reverse ++ a.reverse}
forAll can grab Arbitraries implicitly
![Page 20: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/20.jpg)
But wait, there’s more...
Automatic test case reductionDSL for testing side-effects
Generator and property combinators
See the ScalaCheck web site for info!
![Page 21: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/21.jpg)
References
![Page 22: QuickCheck ClojureCheck ScalaCheck - Meetup](https://reader031.fdocuments.net/reader031/viewer/2022021007/6203943bda24ad121e4b0cc4/html5/thumbnails/22.jpg)
Haskell QuickCheckhttp://fsl.cs.illinois.edu/images/3/3d/QuickL.pdf
http://www.haskell.org/haskellwiki/Introduction_to_QuickCheck1
ScalaCheckhttps://github.com/rickynils/scalacheck
Java QuickCheckhttps://bitbucket.org/blob79/quickcheck
ClojureCheckhttps://github.com/jbondeson/clojurecheck