Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Powerful Testing with test.check

Powerful Testing with test.check

Clojure/West 2014. Slides to accompany https://www.youtube.com/watch?v=JMhNINPo__g.

Unit-testing is a common tool for gaining confidence in code correctness. However, the benefit from these tests is often linear to the number of hand-written test-cases. test.check (formerly simple-check) is a property-based testing tool based on QuickCheck, which allows for thousands of tests with constant effort.

Tests are written as universal quantifications -- properties which should hold true for all input. test.check then randomly generates test cases, for which the property should pass. In this talk, we'll take a look at the foundations of test.check, implementation details regarding shrinking, and see sophisticated tests of concurrent and non-deterministic code.

Reid Draper

March 24, 2014
Tweet

More Decks by Reid Draper

Other Decks in Programming

Transcript

  1. (prop/for-all! [a (gen/vector gen/any)! b (gen/vector gen/any)]! (= (count (concat

    a b))! (+ (count a) (count b))))! universal-quantification
  2. ;; `p` is the aforementioned code! (tc/quick-check 100 p)! ;;

    => {:result true, :num-tests ! 100, :seed 1395110930836}!
  3. any any-printable boolean byte bytes char char- alpha-numeric char-ascii hash-map

    int keyword list map nat neg-int pos-int ratio s-neg-int s-pos- int string string-alpha-numeric string-ascii tuple vector
  4. (gen/sample (gen/vector gen/int))! ([] [1] [2 0] [1 2 -1]

    [] [0] [-4] [] [-8] [4 0 2 -8 -9])! ! vector
  5. (last (gen/sample gen/any-printable))! {:3aBA "~e",! ({"" false} \") ("r" ""

    {{} 0, :y {0 \+}}),! [2 {} [[] {0 :v7}]] -1/4,! (1 2 \') {},! :4 ["" ({0 true})],! {false {}, {(0) (\^)} 0, ("m" [false]) ((true) {}), [[\t] ()] {}} -3}! any
  6. (gen/sample (gen/elements ! [:clojure :haskell :erlang :python :ruby]))! ! (:clojure

    :haskell :haskell :clojure :clojure :python :c lojure :clojure :ruby :ruby)! elements
  7. (gen/sample (gen/frequency ! [[5 (gen/return :weekday)]! [2 (gen/return :weekend)]]))! !

    (:weekday :weekday :weekend :weekday :weekday :weekend : weekend :weekend :weekday :weekday)! frequency
  8. (gen/sample (gen/fmap odd? gen/int))! (false true false true true false

    false false false false)! ! apply odd? to every generated value
  9. ([[0] 0]! [[1 -2] 1]! [[2 2] 2]! [[-3 -3]

    -3]! [[4 -4] -4]! [[2 1] 2]! [[-6 -6 -5 -1] -5]! [[8 -5 6 -6 -6 -5 7 -7] 8]! [[-3 2 -5 -4] -5]! [[7 5] 5])! ! ! tuples of vector and chosen element
  10. [[:disj -108] [:disj -24] [:disj 89] [:transient] [:conj 12] [:disj

    -136] [:transient] [:conj -145] [:conj -8] [:persistent!] [:persistent!] [:conj 25] [:conj 142] [:conj 146] [:persistent!] [:transient] [:conj 95] [:persistent!] [:disj -86] [:transient] [:persistent!] [:transient] [:persistent!] [:conj -109] [:transient] [:transient] [:persistent!] [:disj -6] [:transient] [:persistent!] [:conj -50] [:persistent!] [:conj -166] [:transient] [:conj 136] [:persistent!] [:persistent!] [:transient] [:disj 155] [:persistent!] [:transient] [:transient] [:disj 143] [:persistent!] [:persistent!] [:transient] [:conj -10] [:transient] [:conj -59] [:conj -34] [:transient] [:transient] [:disj 111] [:transient] [:disj -33] [:transient] [:conj -96] [:transient] [:disj 93] [:disj -130] [:conj 88] [:disj 14] [:transient] [:disj 9] [:persistent!] [:disj 86] [:conj 109] [:conj -45] [:persistent!] [:persistent!] [:disj -141] [:conj -14] [:persistent!] [:persistent!] [:conj -104] [:conj -83] [:persistent!] [:persistent!] [:conj -73] [:conj 13] [:persistent!] [:persistent!] [:persistent!] [:disj -14] [:conj -129] [:disj -53] [:transient] [:conj -110] [:conj 60] [:conj 11] [:disj -128] [:disj -42] [:disj 18] [:disj 73] [:disj 33] [:transient] [:persistent!] [:persistent!] [:transient] [:persistent!] [:transient] [:disj -123] [:disj -141] [:conj -26] [:conj -92] [:conj -116] [:conj 101] [:disj -133] [:conj 58] [:transient] [:disj -110] [:persistent!] [:disj 105] [:conj 26] [:conj -110] [:persistent!] [:transient] [:persistent!] [:persistent!] [:disj -5] [:conj 117] [:transient] [:persistent!] [:disj 96] [:persistent!] [:disj 52] [:persistent!] [:disj -132] [:transient] [:transient] [:conj -108] [:disj 121] [:persistent!]]!