Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ The `checking` macro is intended to be used with
'[com.gfredericks.test.chuck.clojure-test :refer [checking]])

(deftest my-test
(checking "that positive numbers are positive" 100
(checking "that positive numbers are positive"
[x gen/s-pos-int]
(is (pos? x))
(is (> x 0))))
Expand Down
38 changes: 27 additions & 11 deletions src/com/gfredericks/test/chuck/clojure_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -106,27 +106,43 @@
(ct/report reports))

(defmacro checking
"A macro intended to replace the testing macro in clojure.test with a
{:doc "A macro intended to replace the testing macro in clojure.test with a
generative form. To make (testing \"doubling\" (is (= (* 2 2) (+ 2 2))))
generative, you simply have to change it to
(checking \"doubling\" 100 [x gen/int] (is (= (* 2 x) (+ x x)))).
(checking \"doubling\" [x gen/int] (is (= (* 2 x) (+ x x)))).

You can optionally pass in a map options instead of the number of tests,
You can optionally pass the same options as test.check's defspec,
which will be passed to `clojure.test.check/quick-check`, e.g.:

(checking \"doubling\" {:num-tests 100 :seed 123 :max-size 10}
(checking \"doubling\" 100 ;; number
[x gen/int]
(is (= (* 2 x) (+ x x))))

(checking \"doubling\" {:num-tests 100 :seed 123 :max-size 10} ;; options map
[x gen/int]
(is (= (* 2 x) (+ x x))))

For background, see
http://blog.colinwilliams.name/blog/2015/01/26/alternative-clojure-dot-test-integration-with-test-dot-check/"
[name num-tests-or-options bindings & body]
`(-testing ~name
(fn []
(let [final-reports# (atom [])]
(qc-and-report-exception final-reports# ~num-tests-or-options ~bindings ~@body)
(doseq [r# @final-reports#]
(-report r#))))))
:arglists '([name bindings & body] [name num-tests-or-options bindings & body])}
[name & check-decl]
(let [[num-tests-or-options bindings body]
(cond
(vector? (second check-decl))
[(first check-decl) (second check-decl) (nnext check-decl)]

(vector? (first check-decl))
[nil (first check-decl) (next check-decl)]

:else (throw (#?(:clj IllegalArgumentException.
:cljs js/Error.) "Arguments to `checking` must be either [name bindings & body] or [name num-tests-or-options bindings & body]")))]
`(-testing ~name
(fn []
(let [final-reports# (atom [])
num-tests-or-options# (tc.clojure-test/process-options ~num-tests-or-options)]
(qc-and-report-exception final-reports# num-tests-or-options# ~bindings ~@body)
(doseq [r# @final-reports#]
(-report r#)))))))

(defmacro for-all
"An alternative to clojure.test.check.properties/for-all that uses
Expand Down
20 changes: 18 additions & 2 deletions test/com/gfredericks/test/chuck/clojure_test_test.cljc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(ns com.gfredericks.test.chuck.clojure-test-test
(:require #?(:clj [clojure.test :refer :all])
#?(:cljs [cljs.test :refer-macros [deftest is]])
#?(:cljs [cljs.test :refer-macros [deftest is testing]])
[clojure.test.check :refer [quick-check]]
[clojure.test.check.generators :as gen]
[com.gfredericks.test.chuck.clojure-test #?(:clj :refer :cljs :refer-macros) [checking for-all]]))
Expand All @@ -12,6 +12,13 @@
(is (< i 0))))

(deftest options-test
;; no option is OK, defaults to 100 tests
(let [nb-runs (atom 0)]
(checking "no option works" [i gen/s-pos-int]
(swap! nb-runs inc)
(is (pos? i)))
(testing "no option means 100 runs (test.check's default)"
(is (= 100 @nb-runs))))
;; empty map is OK, defaults to 100 tests
(checking "strings are strings" {} [s gen/string-ascii]
(is (string? s)))
Expand All @@ -23,7 +30,16 @@
(is (contains? #{-1 0 1} i)))
;; passes because of max-size
(checking "short strings" {:num-tests 100 :max-size 9} [s gen/string-ascii]
(is (< (count s) 10))))
(is (< (count s) 10)))
;; using non-literal expression as option
(let [opts {:max-size 9}]
(checking "short strings again" (assoc opts :num-tests 100) [s gen/string-ascii]
(is (< (count s) 10))))
;; bad options throws
(testing "bad option throws"
(is (thrown? #?(:clj Exception :cljs js/Object)
(eval `(checking "numbers are numbers" "opts as string" [i# gen/int]
(is (integer? i#))))))))

(deftest counter
(checking "increasing" 100 [i gen/s-pos-int]
Expand Down