Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Check Your Work: An Introduction to Property-Ba...
Search
Connor Mendenhall
August 04, 2016
34
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Check Your Work: An Introduction to Property-Based Testing
Connor Mendenhall
August 04, 2016
More Decks by Connor Mendenhall
See All by Connor Mendenhall
Monitor What Matters
ecmendenhall
0
38
Serverless Integration Patterns
ecmendenhall
0
250
Intro to Git
ecmendenhall
0
83
Economics of Web Security
ecmendenhall
0
44
PGP for Developers
ecmendenhall
0
130
Mac_security_basics.pdf
ecmendenhall
0
54
Featured
See All Featured
Chasing Engaging Ingredients in Design
codingconduct
0
240
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
510
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
160
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
510
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
390
Designing for Performance
lara
611
70k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
260
How to train your dragon (web standard)
notwaldorf
97
6.7k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
160
Git: the NoSQL Database
bkeepers
PRO
432
67k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
55k
Transcript
Check Your Work An introduction to property-based testing Connor Mendenhall
@ecmendenhall 8th Light
None
Can we do better?
None
Have you performed the right tests? —“Out of the Tar
Pit”
None
None
None
Values “add(1,2) equals 3” “sort([1,5,3,4]) returns [1,3,4,5]” “MyCoolModel.save() is the
same as MyCoolModel.save().save()”
Properties “add(a,b) equals a+b for all values of a and
b” “sort(list) returns all values in list in ascending order.” “Model.save() is idempotent.”
Prime factors
Prime factors 4 = 2·2 17 = 17 30 =
2·3·5 31878 = 2·3·3·7·11·23
Prime factors 4 = 2·2 17 = 17 30 =
2·3·5 31878 = 2·3·3·7·11·23
Prime factors 4 = 2·2 17 = 17 30 =
2·3·5 31878 = 2·3·3·7·11·23
Prime factors 4 = 2·2 17 = 17 30 =
2·3·5 31878 = 2·3·3·7·11·23
Prime factors user=> (prime-factors 4) [2 2] user=> (prime-factors 17)
[17] user=> (prime-factors 30) [2 3 5] user=> (prime-factors 31878) [2 3 3 7 11 23]
(defn trial-division [n divisor factors] (if (< n 2) factors
(if (= 0 (mod n divisor)) (recur (/ n divisor) divisor (conj factors divisor)) (recur n (inc divisor) factors)))) (defn prime-factors [n] (trial-division n 2 []))
(defn trial-division [n divisor factors] (if (< n 2) factors
(if (= 0 (mod n divisor)) (recur (/ n divisor) divisor (conj factors divisor)) (recur n (inc divisor) factors)))) (defn prime-factors [n] (trial-division n 2 []))
(defn trial-division [n divisor factors] (if (< n 2) factors
(if (= 0 (mod n divisor)) (recur (/ n divisor) divisor (conj factors divisor)) (recur n (inc divisor) factors)))) (defn prime-factors [n] (trial-division n 2 []))
(defn trial-division [n divisor factors] (if (< n 2) factors
(if (= 0 (mod n divisor)) (recur (/ n divisor) divisor (conj factors divisor)) (recur n (inc divisor) factors)))) (defn prime-factors [n] (trial-division n 2 []))
(defn trial-division [n divisor factors] (if (< n 2) factors
(if (= 0 (mod n divisor)) (recur (/ n divisor) divisor (conj factors divisor)) (recur n (inc divisor) factors)))) (defn prime-factors [n] (trial-division n 2 []))
(defn trial-division [n divisor factors] (if (< n 2) factors
(if (= 0 (mod n divisor)) (recur (/ n divisor) divisor (conj factors divisor)) (recur n (inc divisor) factors)))) (defn prime-factors [n] (trial-division n 2 []))
(defn trial-division [n divisor factors] (if (< n 2) factors
(if (= 0 (mod n divisor)) (recur (/ n divisor) divisor (conj factors divisor)) (recur n (inc divisor) factors)))) (defn prime-factors [n] (trial-division n 2 []))
(defn trial-division [n divisor factors] (if (< n 2) factors
(if (= 0 (mod n divisor)) (recur (/ n divisor) divisor (conj factors divisor)) (recur n (inc divisor) factors)))) (defn prime-factors [n] (trial-division n 2 []))
(defn trial-division [n divisor factors] (if (< n 2) factors
(if (= 0 (mod n divisor)) (recur (/ n divisor) divisor (conj factors divisor)) (recur n (inc divisor) factors)))) (defn prime-factors [n] (trial-division n 2 []))
(defn trial-division [n divisor factors] (if (< n 2) factors
(if (= 0 (mod n divisor)) (recur (/ n divisor) divisor (conj factors divisor)) (recur n (inc divisor) factors)))) (defn prime-factors [n] (trial-division n 2 []))
(defn trial-division [n divisor factors] (if (< n 2) factors
(if (= 0 (mod n divisor)) (recur (/ n divisor) divisor (conj factors divisor)) (recur n (inc divisor) factors)))) (defn prime-factors [n] (trial-division n 2 []))
(defn trial-division [n divisor factors] (if (< n 2) factors
(if (= 0 (mod n divisor)) (recur (/ n divisor) divisor (conj factors divisor)) (recur n (inc divisor) factors)))) (defn prime-factors [n] (trial-division n 2 []))
(defn trial-division [n divisor factors] (if (< n 2) factors
(if (= 0 (mod n divisor)) (recur (/ n divisor) divisor (conj factors divisor)) (recur n (inc divisor) factors)))) (defn prime-factors [n] (trial-division n 2 []))
(deftest test-factors-of-one (testing "returns [] for 1" (is (= []
(prime-factors 1)))))
(deftest test-factors-of-two (testing "returns [2] for 2" (is (= [2]
(prime-factors 2)))))
(def primes (load-primes "primes.txt")) (defspec primes-have-one-prime-factor 1000 (testing "A prime's
only prime factor is itself" (prop/for-all [prime (gen/elements primes)] (= [prime] (prime-factors prime)))))
(def primes (load-primes "primes.txt")) (defspec primes-have-one-prime-factor 1000 (testing "A prime's
only prime factor is itself" (prop/for-all [prime (gen/elements primes)] (= [prime] (prime-factors prime)))))
(def primes (load-primes "primes.txt")) (defspec primes-have-one-prime-factor 1000 (testing "A prime's
only prime factor is itself" (prop/for-all [prime (gen/elements primes)] (= [prime] (prime-factors prime)))))
(def primes (load-primes "primes.txt")) (defspec primes-have-one-prime-factor 1000 (testing "A prime's
only prime factor is itself" (prop/for-all [prime (gen/elements primes)] (= [prime] (prime-factors prime)))))
(def primes (load-primes "primes.txt")) (defspec primes-have-one-prime-factor 1000 (testing "A prime's
only prime factor is itself" (prop/for-all [prime (gen/elements primes)] (= [prime] (prime-factors prime)))))
(def primes (load-primes "primes.txt")) (defspec primes-have-one-prime-factor 1000 (testing "A prime's
only prime factor is itself" (prop/for-all [prime (gen/elements primes)] (= [prime] (prime-factors prime)))))
(def primes (load-primes "primes.txt")) (defspec primes-have-one-prime-factor 1000 (testing "A prime's
only prime factor is itself" (prop/for-all [prime (gen/elements primes)] (= [prime] (prime-factors prime)))))
(deftest test-factors-of-two (testing "returns [2 2] for 4" (is (=
[2 2] (prime-factors 4))))) (defspec two-times-prime-returns-two-and-prime 1000 (testing "Factors of 2 * prime = 2 and the prime" (prop/for-all [prime (gen/elements primes)] (= [2 prime] (prime-factors (* 2 prime))))))
(deftest test-factors-of-two (testing "returns [2 2] for 4" (is (=
[2 2] (prime-factors 4))))) (defspec two-times-prime-returns-two-and-prime 1000 (testing "Factors of 2 * prime = 2 and the prime" (prop/for-all [prime (gen/elements primes)] (= [2 prime] (prime-factors (* 2 prime))))))
(deftest test-factors-of-two (testing "returns [2 2] for 4" (is (=
[2 2] (prime-factors 4))))) (defspec two-times-prime-returns-two-and-prime 1000 (testing "Factors of 2 * prime = 2 and the prime" (prop/for-all [prime (gen/elements primes)] (= [2 prime] (prime-factors (* 2 prime))))))
(deftest test-factors-of-nine (testing "returns [3 3] for 9" (is (=
[3 3] (prime-factors 9))))) (defspec check-prime-times-prime-has-two-prime-factors 1000 (testing "Factoring prime * prime returns both primes" (prop/for-all [prime-one (gen/elements primes) prime-two (gen/elements primes)] (= (set [prime-one prime-two]) (set (prime-factors (* prime-one prime-two)))))))
(deftest test-factors-of-nine (testing "returns [3 3] for 9" (is (=
[3 3] (prime-factors 9))))) (defspec check-prime-times-prime-has-two-prime-factors 1000 (testing "Factoring prime * prime returns both primes" (prop/for-all [prime-one (gen/elements primes) prime-two (gen/elements primes)] (= (set [prime-one prime-two]) (set (prime-factors (* prime-one prime-two)))))))
(deftest test-factors-of-nine (testing "returns [3 3] for 9" (is (=
[3 3] (prime-factors 9))))) (defspec check-prime-times-prime-has-two-prime-factors 1000 (testing "Factoring prime * prime returns both primes" (prop/for-all [prime-one (gen/elements primes) prime-two (gen/elements primes)] (= (set [prime-one prime-two]) (set (prime-factors (* prime-one prime-two)))))))
(deftest test-factors-of-nine (testing "returns [3 3] for 9" (is (=
[3 3] (prime-factors 9))))) (defspec check-prime-times-prime-has-two-prime-factors 1000 (testing "Factoring prime * prime returns both primes" (prop/for-all [prime-one (gen/elements primes) prime-two (gen/elements primes)] (= (set [prime-one prime-two]) (set (prime-factors (* prime-one prime-two)))))))
(defspec check-product-of-primes-returns-all-primes 1000 (testing "Factoring the product of a series
of primes returns all the primes" (prop/for-all [prime-seq (gen/vector (gen/elements primes))] (= (sort prime-seq) (prime-factors (apply *' prime-seq))))))
(defspec check-product-of-primes-returns-all-primes 1000 (testing "Factoring the product of a series
of primes returns all the primes" (prop/for-all [prime-seq (gen/vector (gen/elements primes))] (= (sort prime-seq) (prime-factors (apply *' prime-seq))))))
(deftest test-factors-of-some-big-number (testing "returns [2 2 2 3 3 5
13 23 131] for 14100840" (is (= [2 2 2 3 3 5 13 23 131] (prime-factors (* 2 2 3 3 5 13 23 131)))))
$ lein test lein test :only prime-factors.core-test/test-factors-of-some-big-number FAIL in (test-factors-of-some-big-number)
(core_test.clj:32) returns [2 2 2 3 3 5 13 23 131] for 14100840 expected: (= [2 2 2 3 3 5 13 23 131] (prime-factors (* 2 2 3 3 5 13 23 131))) actual: (not (= [2 2 2 3 3 5 13 23 131] [2 2 3 3 5 13 23 131])) Ran 13 tests containing 13 assertions. 1 failures, 0 errors. Tests failed.
$ lein test lein test :only prime-factors.core-test/test-factors-of-some-big-number FAIL in (test-factors-of-some-big-number)
(core_test.clj:32) returns [2 2 2 3 3 5 13 23 131] for 14100840 expected: (= [2 2 2 3 3 5 13 23 131] (prime-factors (* 2 2 3 3 5 13 23 131))) actual: (not (= [2 2 2 3 3 5 13 23 131] [2 2 3 3 5 13 23 131])) Ran 13 tests containing 13 assertions. 1 failures, 0 errors. Tests failed.
(defspec check-product-of-primes-returns-all-primes 1000 (testing "Factoring the product of a series
of primes returns all the primes" (prop/for-all [prime-seq (gen/vector (gen/elements primes))] (= prime-seq (prime-factors (apply *' prime-seq))))))
$ lein test lein test prime-factors.core-check {:result false, :seed 1469999806348,
:failing-size 5, :num-tests 6, :fail [[4483 2251 7309 971 6199]], :shrunk {:total-nodes-visited 87, :depth 17, :result false, :smallest [[3 2]]}, :test-var "check-product-of-primes-returns-all-primes"} FAIL in (check-product-of-a-series-of-primes-returns-all-primes) (clojure_test.cljc:21) expected: result actual: false {:result true, :num-tests 1000, :seed 1469999806440, :test-var "check-two-times-prime-has-two-prime-factors"} {:result true, :num-tests 1000, :seed 1469999807020, :test-var "check-primes-have-one-prime-factor"} {:result true, :num-tests 1000, :seed 1469999807577, :test-var "check-prime-times-prime-has-two-prime-factors"} Tests failed.
$ lein test lein test prime-factors.core-check {:result false, :seed 1469999806348,
:failing-size 5, :num-tests 6, :fail [[4483 2251 7309 971 6199]], :shrunk {:total-nodes-visited 87, :depth 17, :result false, :smallest [[3 2]]}, :test-var "check-product-of-primes-returns-all-primes"} FAIL in (check-product-of-a-series-of-primes-returns-all-primes) (clojure_test.cljc:21) expected: result actual: false {:result true, :num-tests 1000, :seed 1469999806440, :test-var "check-two-times-prime-has-two-prime-factors"} {:result true, :num-tests 1000, :seed 1469999807020, :test-var "check-primes-have-one-prime-factor"} {:result true, :num-tests 1000, :seed 1469999807577, :test-var "check-prime-times-prime-has-two-prime-factors"} Tests failed.
$ lein test lein test prime-factors.core-check {:result false, :seed 1469999806348,
:failing-size 5, :num-tests 6, :fail [[4483 2251 7309 971 6199]], :shrunk {:total-nodes-visited 87, :depth 17, :result false, :smallest [[3 2]]}, :test-var "check-product-of-primes-returns-all-primes"} FAIL in (check-product-of-a-series-of-primes-returns-all-primes) (clojure_test.cljc:21) expected: result actual: false {:result true, :num-tests 1000, :seed 1469999806440, :test-var "check-two-times-prime-has-two-prime-factors"} {:result true, :num-tests 1000, :seed 1469999807020, :test-var "check-primes-have-one-prime-factor"} {:result true, :num-tests 1000, :seed 1469999807577, :test-var "check-prime-times-prime-has-two-prime-factors"} Tests failed.
$ lein test lein test prime-factors.core-check {:result false, :seed 1469999806348,
:failing-size 5, :num-tests 6, :fail [[4483 2251 7309 971 6199]], :shrunk {:total-nodes-visited 87, :depth 17, :result false, :smallest [[3 2]]}, :test-var "check-product-of-primes-returns-all-primes"} FAIL in (check-product-of-a-series-of-primes-returns-all-primes) (clojure_test.cljc:21) expected: result actual: false {:result true, :num-tests 1000, :seed 1469999806440, :test-var "check-two-times-prime-has-two-prime-factors"} {:result true, :num-tests 1000, :seed 1469999807020, :test-var "check-primes-have-one-prime-factor"} {:result true, :num-tests 1000, :seed 1469999807577, :test-var "check-prime-times-prime-has-two-prime-factors"} Tests failed.
$ lein test lein test prime-factors.core-check {:result false, :seed 1469999806348,
:failing-size 5, :num-tests 6, :fail [[4483 2251 7309 971 6199]], :shrunk {:total-nodes-visited 87, :depth 17, :result false, :smallest [[3 2]]}, :test-var "check-product-of-primes-returns-all-primes"} FAIL in (check-product-of-a-series-of-primes-returns-all-primes) (clojure_test.cljc:21) expected: result actual: false {:result true, :num-tests 1000, :seed 1469999806440, :test-var "check-two-times-prime-has-two-prime-factors"} {:result true, :num-tests 1000, :seed 1469999807020, :test-var "check-primes-have-one-prime-factor"} {:result true, :num-tests 1000, :seed 1469999807577, :test-var "check-prime-times-prime-has-two-prime-factors"} Tests failed.
Can we do better?
Show Your Work
Check Your Work Show Your Work