clojure_test.{[clj cljs] -> cljc}
Nicolas Berger authored 8 years ago
Gary Fredericks committed 8 years ago
0 | ; Copyright (c) Rich Hickey, Reid Draper, and contributors. | |
1 | ; All rights reserved. | |
2 | ; The use and distribution terms for this software are covered by the | |
3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) | |
4 | ; which can be found in the file epl-v10.html at the root of this distribution. | |
5 | ; By using this software in any fashion, you are agreeing to be bound by | |
6 | ; the terms of this license. | |
7 | ; You must not remove this notice, or any other, from this software. | |
8 | ||
9 | (ns clojure.test.check.clojure-test | |
10 | (:require [clojure.test :as ct])) | |
11 | ||
12 | (defn assert-check | |
13 | [{:keys [result] :as m}] | |
14 | (prn m) | |
15 | (if (instance? Throwable result) | |
16 | (throw result) | |
17 | (ct/is result))) | |
18 | ||
19 | (def ^:dynamic *default-test-count* 100) | |
20 | ||
21 | (defn process-options | |
22 | {:no-doc true} | |
23 | [options] | |
24 | (cond (nil? options) {:num-tests *default-test-count*} | |
25 | (number? options) {:num-tests options} | |
26 | (map? options) (if (:num-tests options) | |
27 | options | |
28 | (assoc options :num-tests *default-test-count*)) | |
29 | :else (throw (ex-info (str "Invalid defspec options: " (pr-str options)) | |
30 | {:bad-options options})))) | |
31 | ||
32 | (defmacro defspec | |
33 | "Defines a new clojure.test test var that uses `quick-check` to verify | |
34 | [property] with the given [args] (should be a sequence of generators), | |
35 | [default-times] times by default. You can call the function defined as [name] | |
36 | with no arguments to trigger this test directly (i.e., without starting a | |
37 | wider clojure.test run), with a single argument that will override | |
38 | [default-times], or with a map containing any of the keys | |
39 | [:seed :max-size :num-tests]." | |
40 | {:arglists '([name property] [name num-tests? property] [name options? property])} | |
41 | ([name property] `(defspec ~name nil ~property)) | |
42 | ([name options property] | |
43 | ;; consider my shame for introducing a cyclical dependency like this... | |
44 | ;; Don't think we'll know what the solution is until clojure.test.check | |
45 | ;; integration with another test framework is attempted. | |
46 | (require 'clojure.test.check) | |
47 | `(defn ~(vary-meta name assoc | |
48 | ::defspec true | |
49 | :test `#(clojure.test.check.clojure-test/assert-check | |
50 | (assoc (~name) :test-var (str '~name)))) | |
51 | ([] (let [options# (process-options ~options)] | |
52 | (apply ~name (:num-tests options#) (apply concat options#)))) | |
53 | ([~'times & {:keys [~'seed ~'max-size] :as ~'quick-check-opts}] | |
54 | (apply | |
55 | clojure.test.check/quick-check | |
56 | ~'times | |
57 | (vary-meta ~property assoc :name (str '~property)) | |
58 | (apply concat ~'quick-check-opts)))))) | |
59 | ||
60 | (def ^:dynamic *report-trials* | |
61 | "Controls whether property trials should be reported via clojure.test/report. | |
62 | Valid values include: | |
63 | ||
64 | * false - no reporting of trials (default) | |
65 | * a function - will be passed a clojure.test/report-style map containing | |
66 | :clojure.test.check/property and :clojure.test.check/trial slots | |
67 | * true - provides quickcheck-style trial reporting (dots) via | |
68 | `trial-report-dots` | |
69 | ||
70 | (Note that all reporting requires running `quick-check` within the scope of a | |
71 | clojure.test run (via `test-ns`, `test-all-vars`, etc.) | |
72 | ||
73 | Reporting functions offered by clojure.test.check include `trial-report-dots` and | |
74 | `trial-report-periodic` (which prints more verbose trial progress information | |
75 | every `*trial-report-period*` milliseconds." | |
76 | false) | |
77 | ||
78 | (def ^:dynamic *report-shrinking* | |
79 | "If true, a verbose report of the property being tested, the | |
80 | failing return value, and the arguments provoking that failure is emitted | |
81 | prior to the start of the shrinking search." | |
82 | false) | |
83 | ||
84 | (def ^:dynamic *trial-report-period* | |
85 | "Milliseconds between reports emitted by `trial-report-periodic`." | |
86 | 10000) | |
87 | ||
88 | (def ^:private last-trial-report (atom 0)) | |
89 | ||
90 | (let [begin-test-var-method (get-method ct/report :begin-test-var)] | |
91 | (defmethod ct/report :begin-test-var [m] | |
92 | (reset! last-trial-report (System/currentTimeMillis)) | |
93 | (when begin-test-var-method (begin-test-var-method m)))) | |
94 | ||
95 | (defn- get-property-name | |
96 | [{property-fun ::property :as report-map}] | |
97 | (or (-> property-fun meta :name) (ct/testing-vars-str report-map))) | |
98 | ||
99 | (defn trial-report-periodic | |
100 | "Intended to be bound as the value of `*report-trials*`; will emit a verbose | |
101 | status every `*trial-report-period*` milliseconds, like this one: | |
102 | ||
103 | Passing trial 3286 / 5000 for (your-test-var-name-here) (:)" | |
104 | [m] | |
105 | (let [t (System/currentTimeMillis)] | |
106 | (when (> (- t *trial-report-period*) @last-trial-report) | |
107 | (ct/with-test-out | |
108 | (println "Passing trial" (-> m ::trial first) "/" (-> m ::trial second) | |
109 | "for" (get-property-name m))) | |
110 | (reset! last-trial-report t)))) | |
111 | ||
112 | (defn trial-report-dots | |
113 | "Intended to be bound as the value of `*report-trials*`; will emit a single | |
114 | dot every 1000 trials reported." | |
115 | [{[so-far total] ::trial}] | |
116 | (when (pos? so-far) | |
117 | (when (zero? (mod so-far 1000)) | |
118 | (print ".") | |
119 | (flush)) | |
120 | (when (== so-far total) (println)))) | |
121 | ||
122 | (defmethod ct/report ::trial [m] | |
123 | (when-let [trial-report-fn (and *report-trials* | |
124 | (if (true? *report-trials*) | |
125 | trial-report-dots | |
126 | *report-trials*))] | |
127 | (trial-report-fn m))) | |
128 | ||
129 | (defmethod ct/report ::shrinking [m] | |
130 | (when *report-shrinking* | |
131 | (ct/with-test-out | |
132 | (println "Shrinking" (get-property-name m) | |
133 | "starting with parameters" (pr-str (::params m)))))) | |
134 | ||
135 | (defn report-trial | |
136 | [property-fun so-far num-tests] | |
137 | (ct/report {:type ::trial | |
138 | ::property property-fun | |
139 | ::trial [so-far num-tests]})) | |
140 | ||
141 | (defn report-failure | |
142 | [property-fun result trial-number failing-params] | |
143 | ;; TODO this is wrong, makes it impossible to clojure.test quickchecks that | |
144 | ;; should fail... | |
145 | #_(ct/report (if (instance? Throwable result) | |
146 | {:type :error | |
147 | :message (.getMessage result) | |
148 | :actual result} | |
149 | {:type :fail | |
150 | :expected true | |
151 | :actual result})) | |
152 | (ct/report {:type ::shrinking | |
153 | ::property property-fun | |
154 | ::params (vec failing-params)})) |
0 | ; Copyright (c) Rich Hickey, Reid Draper, and contributors. | |
1 | ; All rights reserved. | |
2 | ; The use and distribution terms for this software are covered by the | |
3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) | |
4 | ; which can be found in the file epl-v10.html at the root of this distribution. | |
5 | ; By using this software in any fashion, you are agreeing to be bound by | |
6 | ; the terms of this license. | |
7 | ; You must not remove this notice, or any other, from this software. | |
8 | ||
9 | (ns clojure.test.check.clojure-test | |
10 | (:require #?(:clj [clojure.test :as ct] | |
11 | :cljs [cljs.test :as ct :include-macros true]))) | |
12 | ||
13 | (defn exception-like? [v] | |
14 | (instance? #?(:clj Throwable :cljs js/Error) v)) | |
15 | ||
16 | (defn assert-check | |
17 | [{:keys [result] :as m}] | |
18 | (prn m) | |
19 | (if (exception-like? result) | |
20 | (throw result) | |
21 | (ct/is result))) | |
22 | ||
23 | (def ^:dynamic *default-test-count* 100) | |
24 | ||
25 | (defn process-options | |
26 | {:no-doc true} | |
27 | [options] | |
28 | (cond (nil? options) {:num-tests *default-test-count*} | |
29 | (number? options) {:num-tests options} | |
30 | (map? options) (if (:num-tests options) | |
31 | options | |
32 | (assoc options :num-tests *default-test-count*)) | |
33 | :else (throw (ex-info (str "Invalid defspec options: " (pr-str options)) | |
34 | {:bad-options options})))) | |
35 | ||
36 | #?(:clj | |
37 | (defmacro defspec | |
38 | "Defines a new clojure.test test var that uses `quick-check` to verify | |
39 | [property] with the given [args] (should be a sequence of generators), | |
40 | [default-times] times by default. You can call the function defined as [name] | |
41 | with no arguments to trigger this test directly (i.e., without starting a | |
42 | wider clojure.test run), with a single argument that will override | |
43 | [default-times], or with a map containing any of the keys | |
44 | [:seed :max-size :num-tests]." | |
45 | {:arglists '([name property] [name num-tests? property] [name options? property])} | |
46 | ([name property] `(defspec ~name nil ~property)) | |
47 | ([name options property] | |
48 | ;; consider my shame for introducing a cyclical dependency like this... | |
49 | ;; Don't think we'll know what the solution is until clojure.test.check | |
50 | ;; integration with another test framework is attempted. | |
51 | (require 'clojure.test.check) | |
52 | `(defn ~(vary-meta name assoc | |
53 | ::defspec true | |
54 | :test `#(clojure.test.check.clojure-test/assert-check | |
55 | (assoc (~name) :test-var (str '~name)))) | |
56 | ([] (let [options# (process-options ~options)] | |
57 | (apply ~name (:num-tests options#) (apply concat options#)))) | |
58 | ([~'times & {:keys [~'seed ~'max-size] :as ~'quick-check-opts}] | |
59 | (apply | |
60 | clojure.test.check/quick-check | |
61 | ~'times | |
62 | (vary-meta ~property assoc :name (str '~property)) | |
63 | (apply concat ~'quick-check-opts))))))) | |
64 | ||
65 | (def ^:dynamic *report-trials* | |
66 | "Controls whether property trials should be reported via clojure.test/report. | |
67 | Valid values include: | |
68 | ||
69 | * false - no reporting of trials (default) | |
70 | * a function - will be passed a clojure.test/report-style map containing | |
71 | :clojure.test.check/property and :clojure.test.check/trial slots | |
72 | * true - provides quickcheck-style trial reporting (dots) via | |
73 | `trial-report-dots` | |
74 | ||
75 | (Note that all reporting requires running `quick-check` within the scope of a | |
76 | clojure.test run (via `test-ns`, `test-all-vars`, etc.) | |
77 | ||
78 | Reporting functions offered by clojure.test.check include `trial-report-dots` and | |
79 | `trial-report-periodic` (which prints more verbose trial progress information | |
80 | every `*trial-report-period*` milliseconds." | |
81 | false) | |
82 | ||
83 | (def ^:dynamic *report-shrinking* | |
84 | "If true, a verbose report of the property being tested, the | |
85 | failing return value, and the arguments provoking that failure is emitted | |
86 | prior to the start of the shrinking search." | |
87 | false) | |
88 | ||
89 | (def ^:dynamic *trial-report-period* | |
90 | "Milliseconds between reports emitted by `trial-report-periodic`." | |
91 | 10000) | |
92 | ||
93 | (def ^:private last-trial-report (atom 0)) | |
94 | ||
95 | (defn get-current-time-millis [] | |
96 | #?(:clj (System/currentTimeMillis) | |
97 | :cljs (.valueOf (js/Date.)))) | |
98 | ||
99 | (let [begin-test-var-method (get-method ct/report #?(:clj :begin-test-var | |
100 | :cljs [::ct/default :begin-test-var]))] | |
101 | (defmethod ct/report #?(:clj :begin-test-var | |
102 | :cljs [::ct/default :begin-test]) [m] | |
103 | (reset! last-trial-report (get-current-time-millis)) | |
104 | (when begin-test-var-method (begin-test-var-method m)))) | |
105 | ||
106 | (defn- get-property-name | |
107 | [{property-fun ::property :as report-map}] | |
108 | (or (-> property-fun meta :name) (ct/testing-vars-str report-map))) | |
109 | ||
110 | (defn with-test-out* [f] | |
111 | #?(:clj (ct/with-test-out (f)) | |
112 | :cljs (f))) | |
113 | ||
114 | (defn trial-report-periodic | |
115 | "Intended to be bound as the value of `*report-trials*`; will emit a verbose | |
116 | status every `*trial-report-period*` milliseconds, like this one: | |
117 | ||
118 | Passing trial 3286 / 5000 for (your-test-var-name-here) (:)" | |
119 | [m] | |
120 | (let [t (get-current-time-millis)] | |
121 | (when (> (- t *trial-report-period*) @last-trial-report) | |
122 | (with-test-out* | |
123 | (fn [] | |
124 | (println "Passing trial" | |
125 | (-> m ::trial first) "/" (-> m ::trial second) | |
126 | "for" (get-property-name m)))) | |
127 | (reset! last-trial-report t)))) | |
128 | ||
129 | (defn trial-report-dots | |
130 | "Intended to be bound as the value of `*report-trials*`; will emit a single | |
131 | dot every 1000 trials reported." | |
132 | [{[so-far total] ::trial}] | |
133 | (when (pos? so-far) | |
134 | (when (zero? (mod so-far 1000)) | |
135 | (print ".") | |
136 | (flush)) | |
137 | (when (== so-far total) (println)))) | |
138 | ||
139 | (defmethod ct/report #?(:clj ::trial :cljs [::ct/default ::trial]) [m] | |
140 | (when-let [trial-report-fn (and *report-trials* | |
141 | (if (true? *report-trials*) | |
142 | trial-report-dots | |
143 | *report-trials*))] | |
144 | (trial-report-fn m))) | |
145 | ||
146 | (defmethod ct/report #?(:clj ::shrinking :cljs [::ct/default ::shrinking]) [m] | |
147 | (when *report-shrinking* | |
148 | (with-test-out* | |
149 | (fn [] | |
150 | (println "Shrinking" (get-property-name m) | |
151 | "starting with parameters" (pr-str (::params m))))))) | |
152 | ||
153 | (defn report-trial | |
154 | [property-fun so-far num-tests] | |
155 | (ct/report {:type ::trial | |
156 | ::property property-fun | |
157 | ::trial [so-far num-tests]})) | |
158 | ||
159 | (defn report-failure | |
160 | [property-fun result trial-number failing-params] | |
161 | ;; TODO this is wrong, makes it impossible to clojure.test quickchecks that | |
162 | ;; should fail... | |
163 | #_(ct/report (if (exception-like? result) | |
164 | {:type :error | |
165 | :message (.getMessage result) | |
166 | :actual result} | |
167 | {:type :fail | |
168 | :expected true | |
169 | :actual result})) | |
170 | (ct/report {:type ::shrinking | |
171 | ::property property-fun | |
172 | ::params (vec failing-params)})) |
0 | ; Copyright (c) Rich Hickey, Reid Draper, and contributors. | |
1 | ; All rights reserved. | |
2 | ; The use and distribution terms for this software are covered by the | |
3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) | |
4 | ; which can be found in the file epl-v10.html at the root of this distribution. | |
5 | ; By using this software in any fashion, you are agreeing to be bound by | |
6 | ; the terms of this license. | |
7 | ; You must not remove this notice, or any other, from this software. | |
8 | ||
9 | (ns clojure.test.check.clojure-test | |
10 | (:require-macros clojure.test.check.clojure-test) | |
11 | (:require [cljs.test :as ct :include-macros true])) | |
12 | ||
13 | (defn- assert-check | |
14 | [{:keys [result] :as m}] | |
15 | (prn m) | |
16 | (if (instance? js/Error result) | |
17 | (throw result) | |
18 | (ct/is result))) | |
19 | ||
20 | (def ^:dynamic *default-test-count* 100) | |
21 | ||
22 | (defn process-options | |
23 | {:no-doc true} | |
24 | [options] | |
25 | (cond (nil? options) {:num-tests *default-test-count*} | |
26 | (number? options) {:num-tests options} | |
27 | (map? options) (if (:num-tests options) | |
28 | options | |
29 | (assoc options :num-tests *default-test-count*)) | |
30 | :else (throw (ex-info (str "Invalid defspec options: " (pr-str options)) | |
31 | {:bad-options options})))) | |
32 | ||
33 | (def ^:dynamic *report-trials* | |
34 | "Controls whether property trials should be reported via clojure.test/report. | |
35 | Valid values include: | |
36 | ||
37 | * false - no reporting of trials (default) | |
38 | * a function - will be passed a clojure.test/report-style map containing | |
39 | :clojure.test.check/property and :clojure.test.check/trial slots | |
40 | * true - provides quickcheck-style trial reporting (dots) via | |
41 | `trial-report-dots` | |
42 | ||
43 | (Note that all reporting requires running `quick-check` within the scope of a | |
44 | clojure.test run (via `test-ns`, `test-all-vars`, etc.) | |
45 | ||
46 | Reporting functions offered by clojure.test.check include `trial-report-dots` and | |
47 | `trial-report-periodic` (which prints more verbose trial progress information | |
48 | every `*trial-report-period*` milliseconds." | |
49 | false) | |
50 | ||
51 | (def ^:dynamic *report-shrinking* | |
52 | "If true, a verbose report of the property being tested, the | |
53 | failing return value, and the arguments provoking that failure is emitted | |
54 | prior to the start of the shrinking search." | |
55 | false) | |
56 | ||
57 | (def ^:dynamic *trial-report-period* | |
58 | "Milliseconds between reports emitted by `trial-report-periodic`." | |
59 | 10000) | |
60 | ||
61 | (def ^:private last-trial-report (atom 0)) | |
62 | ||
63 | (let [begin-test-var-method (get-method ct/report [::ct/default :begin-test-var])] | |
64 | (defmethod ct/report [::ct/default :begin-test-var] [m] | |
65 | (reset! last-trial-report (.valueOf (js/Date.))) | |
66 | (when begin-test-var-method (begin-test-var-method m)))) | |
67 | ||
68 | (defn- get-property-name | |
69 | [{property-fun ::property :as report-map}] | |
70 | (or (-> property-fun meta :name) (ct/testing-vars-str report-map))) | |
71 | ||
72 | (defn trial-report-periodic | |
73 | "Intended to be bound as the value of `*report-trials*`; will emit a verbose | |
74 | status every `*trial-report-period*` milliseconds, like this one: | |
75 | ||
76 | Passing trial 3286 / 5000 for (your-test-var-name-here) (:)" | |
77 | [m] | |
78 | (let [t (.valueOf (js/Date.))] | |
79 | (when (> (- t *trial-report-period*) @last-trial-report) | |
80 | (println "Passing trial" (-> m ::trial first) "/" (-> m ::trial second) | |
81 | "for" (get-property-name m)) | |
82 | (reset! last-trial-report t)))) | |
83 | ||
84 | (defn trial-report-dots | |
85 | "Intended to be bound as the value of `*report-trials*`; will emit a single | |
86 | dot every 1000 trials reported." | |
87 | [{[so-far total] ::trial}] | |
88 | (when (pos? so-far) | |
89 | (when (zero? (mod so-far 1000)) | |
90 | (print ".") | |
91 | (flush)) | |
92 | (when (== so-far total) (println)))) | |
93 | ||
94 | (defmethod ct/report [::ct/default ::trial] [m] | |
95 | (when-let [trial-report-fn (and *report-trials* | |
96 | (if (true? *report-trials*) | |
97 | trial-report-dots | |
98 | *report-trials*))] | |
99 | (trial-report-fn m))) | |
100 | ||
101 | (defmethod ct/report [::ct/default ::shrinking] [m] | |
102 | (when *report-shrinking* | |
103 | (println "Shrinking" (get-property-name m) | |
104 | "starting with parameters" (pr-str (::params m))))) | |
105 | ||
106 | (defn report-trial | |
107 | [property-fun so-far num-tests] | |
108 | (ct/report {:type ::trial | |
109 | ::property property-fun | |
110 | ::trial [so-far num-tests]})) | |
111 | ||
112 | (defn report-failure | |
113 | [property-fun result trial-number failing-params] | |
114 | ;; TODO this is wrong, makes it impossible to clojure.test quickchecks that | |
115 | ;; should fail... | |
116 | #_(ct/report (if (instance? Throwable result) | |
117 | {:type :error | |
118 | :message (.getMessage result) | |
119 | :actual result} | |
120 | {:type :fail | |
121 | :expected true | |
122 | :actual result})) | |
123 | (ct/report {:type ::shrinking | |
124 | ::property property-fun | |
125 | ::params (vec failing-params)})) | |
126 |
0 | ; Copyright (c) Rich Hickey, Reid Draper, and contributors. | |
1 | ; All rights reserved. | |
2 | ; The use and distribution terms for this software are covered by the | |
3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) | |
4 | ; which can be found in the file epl-v10.html at the root of this distribution. | |
5 | ; By using this software in any fashion, you are agreeing to be bound by | |
6 | ; the terms of this license. | |
7 | ; You must not remove this notice, or any other, from this software. | |
8 | ||
9 | (ns clojure.test.check.clojure-test-test | |
10 | (:use clojure.test) | |
11 | (:require [clojure.test.check.generators :as gen] | |
12 | [clojure.test.check.properties :as prop] | |
13 | [clojure.test.check.clojure-test :as ct :refer (defspec)])) | |
14 | ||
15 | (defspec default-trial-counts | |
16 | (prop/for-all* [gen/int] (constantly true))) | |
17 | ||
18 | (defspec trial-counts 5000 | |
19 | (prop/for-all* [gen/int] (constantly true))) | |
20 | ||
21 | (defspec long-running-spec 1000 | |
22 | (prop/for-all* [] #(do (Thread/sleep 1) true))) | |
23 | ||
24 | (defn- vector-elements-are-unique* | |
25 | [v] | |
26 | (== (count v) (count (distinct v)))) | |
27 | ||
28 | (def ^:private vector-elements-are-unique | |
29 | (prop/for-all* | |
30 | [(gen/vector gen/int)] | |
31 | vector-elements-are-unique*)) | |
32 | ||
33 | (defspec this-is-supposed-to-fail 100 vector-elements-are-unique) | |
34 | ||
35 | (defn- capture-test-var | |
36 | [v] | |
37 | (doto (with-out-str (binding [*test-out* *out*] (test-var v))) | |
38 | println)) | |
39 | ||
40 | (defn test-ns-hook | |
41 | [] | |
42 | (is (-> (capture-test-var #'default-trial-counts) | |
43 | read-string | |
44 | :num-tests | |
45 | (= ct/*default-test-count*))) | |
46 | ||
47 | (is (-> (capture-test-var #'trial-counts) | |
48 | read-string | |
49 | (select-keys [:test-var :result :num-tests]) | |
50 | (= {:test-var "trial-counts", :result true, :num-tests 5000}))) | |
51 | ||
52 | (binding [ct/*report-trials* true] | |
53 | (let [output (capture-test-var #'trial-counts)] | |
54 | (is (re-matches #"(?s)\.{5}.+" output)))) | |
55 | ||
56 | (binding [ct/*report-trials* ct/trial-report-periodic | |
57 | ct/*trial-report-period* 500] | |
58 | (is (re-seq | |
59 | #"(Passing trial \d{3} / 1000 for .+\n)+" | |
60 | (capture-test-var #'long-running-spec)))) | |
61 | ||
62 | (let [[report-counters stdout] | |
63 | (binding [ct/*report-shrinking* true | |
64 | ; need to keep the failure of this-is-supposed-to-fail from | |
65 | ; affecting the clojure.test.check test run | |
66 | *report-counters* (ref *initial-report-counters*)] | |
67 | [*report-counters* (capture-test-var #'this-is-supposed-to-fail)])] | |
68 | (is (== 1 (:fail @report-counters))) | |
69 | (is (re-seq | |
70 | #"(?s)Shrinking vector-elements-are-unique starting with parameters \[\[.+" | |
71 | stdout)))) |
0 | ; Copyright (c) Rich Hickey, Reid Draper, and contributors. | |
1 | ; All rights reserved. | |
2 | ; The use and distribution terms for this software are covered by the | |
3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) | |
4 | ; which can be found in the file epl-v10.html at the root of this distribution. | |
5 | ; By using this software in any fashion, you are agreeing to be bound by | |
6 | ; the terms of this license. | |
7 | ; You must not remove this notice, or any other, from this software. | |
8 | ||
9 | (ns clojure.test.check.clojure-test-test | |
10 | #?(:clj (:use clojure.test)) | |
11 | (:require #?@(:cljs | |
12 | [[cljs.test :as test :refer [test-var] :refer-macros [is]] | |
13 | [cljs.reader :refer [read-string]]]) | |
14 | [clojure.test.check.generators :as gen] | |
15 | [clojure.test.check.properties :as prop #?@(:cljs [:include-macros true])] | |
16 | [clojure.test.check.clojure-test :as ct #?@(:clj [:refer (defspec)] | |
17 | :cljs [:refer-macros (defspec)])])) | |
18 | ||
19 | (defspec default-trial-counts | |
20 | (prop/for-all* [gen/int] (constantly true))) | |
21 | ||
22 | (defspec trial-counts 5000 | |
23 | (prop/for-all* [gen/int] (constantly true))) | |
24 | ||
25 | ;; NOTE: No Thread/sleep in JS, so no :cljs version - David | |
26 | #?(:clj | |
27 | (defspec long-running-spec 1000 | |
28 | (prop/for-all* [] #(do (Thread/sleep 1) true)))) | |
29 | ||
30 | (defn- vector-elements-are-unique* | |
31 | [v] | |
32 | (== (count v) (count (distinct v)))) | |
33 | ||
34 | (def ^:private vector-elements-are-unique | |
35 | (prop/for-all* | |
36 | [(gen/vector gen/int)] | |
37 | vector-elements-are-unique*)) | |
38 | ||
39 | (defspec this-is-supposed-to-fail 100 vector-elements-are-unique) | |
40 | ||
41 | (defn- capture-test-var | |
42 | [v] | |
43 | (doto (with-out-str #?(:clj (binding [*test-out* *out*] (test-var v)) | |
44 | :cljs (test-var v))) | |
45 | println)) | |
46 | ||
47 | (defn test-ns-hook | |
48 | [] | |
49 | (is (-> (capture-test-var #'default-trial-counts) | |
50 | read-string | |
51 | :num-tests | |
52 | (= ct/*default-test-count*))) | |
53 | ||
54 | (is (-> (capture-test-var #'trial-counts) | |
55 | read-string | |
56 | (select-keys [:test-var :result :num-tests]) | |
57 | (= {:test-var "trial-counts", :result true, :num-tests 5000}))) | |
58 | ||
59 | (binding [ct/*report-trials* true] | |
60 | (let [output (capture-test-var #'trial-counts)] | |
61 | (is (re-matches #?(:clj #"(?s)\.{5}.+" | |
62 | :cljs #"\.{5}[\s\S]+") | |
63 | output)))) | |
64 | ||
65 | ;; NOTE: No Thread/sleep in JS - David | |
66 | #?(:clj | |
67 | (binding [ct/*report-trials* ct/trial-report-periodic | |
68 | ct/*trial-report-period* 500] | |
69 | (is (re-seq | |
70 | #"(Passing trial \d{3} / 1000 for .+\n)+" | |
71 | (capture-test-var #'long-running-spec))))) | |
72 | ||
73 | (let [[report-counters stdout] | |
74 | #?(:clj | |
75 | (binding [ct/*report-shrinking* true | |
76 | ; need to keep the failure of this-is-supposed-to-fail from | |
77 | ; affecting the clojure.test.check test run | |
78 | *report-counters* (ref *initial-report-counters*)] | |
79 | (let [out (capture-test-var #'this-is-supposed-to-fail)] | |
80 | [@*report-counters* out])) | |
81 | ||
82 | :cljs | |
83 | (binding [ct/*report-shrinking* true] | |
84 | ;; need to keep the failure of this-is-supposed-to-fail from | |
85 | ;; affecting the clojure.test.check test run | |
86 | (let [restore-env (test/get-current-env) | |
87 | _ (test/set-env! (test/empty-env)) | |
88 | report-str (capture-test-var #'this-is-supposed-to-fail) | |
89 | env (test/get-current-env)] | |
90 | (test/set-env! restore-env) | |
91 | [(:report-counters env) report-str])))] | |
92 | (is (== 1 (:fail report-counters))) | |
93 | (is (re-seq | |
94 | #?(:clj | |
95 | #"(?s)Shrinking vector-elements-are-unique starting with parameters \[\[.+" | |
96 | ||
97 | :cljs | |
98 | #"Shrinking vector-elements-are-unique starting with parameters \[\[[\s\S]+") | |
99 | stdout)))) |
0 | ; Copyright (c) Rich Hickey, Reid Draper, and contributors. | |
1 | ; All rights reserved. | |
2 | ; The use and distribution terms for this software are covered by the | |
3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) | |
4 | ; which can be found in the file epl-v10.html at the root of this distribution. | |
5 | ; By using this software in any fashion, you are agreeing to be bound by | |
6 | ; the terms of this license. | |
7 | ; You must not remove this notice, or any other, from this software. | |
8 | ||
9 | (ns clojure.test.check.clojure-test-test | |
10 | (:require [cljs.test :as test :refer [test-var] :refer-macros [is]] | |
11 | [clojure.test.check.generators :as gen] | |
12 | [clojure.test.check.properties :as prop :include-macros true] | |
13 | [clojure.test.check.clojure-test :as ct :refer-macros [defspec]] | |
14 | [cljs.reader :refer [read-string]])) | |
15 | ||
16 | (defspec default-trial-counts | |
17 | (prop/for-all* [gen/int] (constantly true))) | |
18 | ||
19 | (defspec trial-counts 5000 | |
20 | (prop/for-all* [gen/int] (constantly true))) | |
21 | ||
22 | ;; NOTE: No Thread/sleep in JS - David | |
23 | ;; (defspec long-running-spec 1000 | |
24 | ;; (prop/for-all* [] #(do (Thread/sleep 1) true))) | |
25 | ||
26 | (defn- vector-elements-are-unique* | |
27 | [v] | |
28 | (== (count v) (count (distinct v)))) | |
29 | ||
30 | (def ^:private vector-elements-are-unique | |
31 | (prop/for-all* | |
32 | [(gen/vector gen/int)] | |
33 | vector-elements-are-unique*)) | |
34 | ||
35 | (defspec this-is-supposed-to-fail 100 vector-elements-are-unique) | |
36 | ||
37 | (defn- capture-test-var | |
38 | [v] | |
39 | (doto (with-out-str (test-var v)) | |
40 | print)) | |
41 | ||
42 | (defn test-ns-hook | |
43 | [] | |
44 | (let [out-str (capture-test-var #'default-trial-counts) | |
45 | num-tests (-> out-str | |
46 | read-string | |
47 | :num-tests)] | |
48 | (is (= num-tests ct/*default-test-count*))) | |
49 | ||
50 | (is (-> (capture-test-var #'trial-counts) | |
51 | read-string | |
52 | (select-keys [:test-var :result :num-tests]) | |
53 | (= {:test-var "trial-counts", :result true, :num-tests 5000}))) | |
54 | ||
55 | (binding [ct/*report-trials* true] | |
56 | (let [output (capture-test-var #'trial-counts)] | |
57 | (is (re-matches #"\.{5}[\s\S]+" output)))) | |
58 | ||
59 | ;; NOTE: No Thread/sleep in JS - David | |
60 | ;; (binding [ct/*report-trials* ct/trial-report-periodic | |
61 | ;; ct/*trial-report-period* 500] | |
62 | ;; (is (re-seq | |
63 | ;; #"(Passing trial \d{3} / 1000 for .+\n)+" | |
64 | ;; (capture-test-var #'long-running-spec)))) | |
65 | ||
66 | (let [[report-counters report-str] | |
67 | (binding [ct/*report-shrinking* true] | |
68 | ;; need to keep the failure of this-is-supposed-to-fail from | |
69 | ;; affecting the clojure.test.check test run | |
70 | (let [restore-env (test/get-current-env) | |
71 | _ (test/set-env! (test/empty-env)) | |
72 | report-str (capture-test-var #'this-is-supposed-to-fail) | |
73 | env (test/get-current-env)] | |
74 | (test/set-env! restore-env) | |
75 | [(:report-counters env) report-str]))] | |
76 | (is (== 1 (:fail report-counters))) | |
77 | (is (re-seq | |
78 | #"Shrinking vector-elements-are-unique starting with parameters \[\[[\s\S]+" | |
79 | report-str)))) | |
80 |