simple-check is a Clojure property-based testing tool inspired by QuickCheck. The core idea of simple-check (and QuickCheck) is that instead of enumerating expected input and output for unit tests, you write properties about your function that should hold true for all inputs. For example, for all lists L, the count of L should equal the count of the reverse of L. Furthermore, reversing the list twice should equal the original list.
To write simple-check tests, you'll do two things: use and create generators
that generate random input for your function, and test that your function
behaves well under these input. When a property fails, by returning something
false or nil, simple-check will try and find 'smaller' input for which the
test still fails. This feature is called shrinking. You can find API
documentation here, and some example usage
below. Release notes
for each version are available in CHANGELOG.markdown.
[reiddraper/simple-check "0.4.0"]<dependency>
<groupId>reiddraper</groupId>
<artifactId>simple-check</artifactId>
<version>0.4.0</version>
</dependency>(require '[simple-check.core :as sc])
(require '[simple-check.generators :as gen])
(require '[simple-check.properties :as prop])
;; a passing test
(sc/quick-check 100
(prop/for-all [(gen/vector gen/int)]
#(= % (reverse (reverse %)))))
;; {:result true, :num-tests 100 :seed 1371257283560}
;; a failing test
(sc/quick-check 100
(prop/for-all [gen/int gen/int]
#(> (+ %1 %2) %)))
;; {:result false,
;; :failing-size 4,
;; :num-tests 3,
;; :fail [-2 -4],
;; :shrunk {:total-nodes-visited 6, depth 3, :smallest [0 0]}}There is a macro called defspec that allows you to succinctly write
properties that run under the clojure.test runner, for example:
(defspec first-element-is-min-after-sorting ;; the name of the test
100 ;; the number of iterations for simple-check to test
(prop/for-all [v (such-that not-empty (gen/vector gen/int))]
(= (apply min v)
(first (sorted v)))))See more examples in core_test.clj.
-
Nested properties allow you to write properties that depend on values generated in an outer property. For example:
(for-all [(gen/vector gen/int)] (fn [v] (for-all [(gen/elements v)] (fn [e] (some #{e} v)))))
Copyright © 2013 Reid Draper
Distributed under the Eclipse Public License, the same as Clojure.