|
25 | 25 | (defn- bad-usage [s]
|
26 | 26 | `(throw (IllegalArgumentException.
|
27 | 27 | (str ~s " should only be used inside expect"))))
|
28 |
| -(defmacro in [& _] (bad-usage "in")) |
29 |
| -(defmacro from-each [& _] (bad-usage "from-each")) |
30 |
| -(defmacro more-of [& _] (bad-usage "more-of")) |
31 |
| -(defmacro more-> [& _] (bad-usage "more->")) |
32 |
| -(defmacro more [& _] (bad-usage "more")) |
| 28 | +(defmacro ^:no-doc in [& _] (bad-usage "in")) |
| 29 | +(defmacro ^:no-doc from-each [& _] (bad-usage "from-each")) |
| 30 | +(defmacro ^:no-doc more-of [& _] (bad-usage "more-of")) |
| 31 | +(defmacro ^:no-doc more-> [& _] (bad-usage "more->")) |
| 32 | +(defmacro ^:no-doc more [& _] (bad-usage "more")) |
33 | 33 |
|
34 |
| -(defn spec? [e] |
| 34 | +(defn ^:no-doc spec? [e] |
35 | 35 | (and (keyword? e)
|
36 | 36 | (try
|
37 | 37 | (require 'clojure.spec.alpha)
|
|
78 | 78 | (list '~'not (list '~'=? e# a#)))}))
|
79 | 79 | r#)))
|
80 | 80 |
|
81 |
| -(defmacro ? |
| 81 | +(defmacro ^:no-doc ? |
82 | 82 | "Wrapper for forms that might throw an exception so exception class names
|
83 | 83 | can be used as predicates. This is only needed for more-> so that you can
|
84 | 84 | thread exceptions into code that can parse information out of them, to be
|
85 | 85 | used with various expect predicates."
|
86 | 86 | [form]
|
87 | 87 | `(try ~form (catch Throwable t# t#)))
|
88 | 88 |
|
89 |
| -(defn all-report |
| 89 | +(defn ^:no-doc all-report |
90 | 90 | "Given an atom in which to accumulate results, return a function that
|
91 | 91 | can be used in place of clojure.test/do-report, which simply remembers
|
92 | 92 | all the reported results.
|
|
97 | 97 | (swap! store update (:type m) (fnil conj []) m)))
|
98 | 98 |
|
99 | 99 | (defmacro expect
|
100 |
| - "Translate Expectations DSL to clojure.test language." |
| 100 | + "Translate Expectations DSL to clojure.test language. |
| 101 | +
|
| 102 | + These are approximate translations for the most basic forms: |
| 103 | +
|
| 104 | + `(expect actual)` => `(is actual)` |
| 105 | + `(expect expected actual)` => `(is (= expected actual))` |
| 106 | + `(expect predicate actual)` => `(is (predicate actual))` |
| 107 | + `(expect regex actual)` => `(is (re-find regex actual))` |
| 108 | + `(expect ClassName actual)` => `(is (instance? ClassName actual))` |
| 109 | + `(expect ExceptionType actual)` => `(is (thrown? ExceptionType actual))` |
| 110 | + `(expect spec actual)` => `(is (s/valid? spec actual))` |
| 111 | +
|
| 112 | + In addition, `actual` can be `(from-each [x coll] (computation-of x))` |
| 113 | + or `(in set-of-results)` or `(in larger-hash-map)`. |
| 114 | +
|
| 115 | + Also, `expect` can be one of `(more predicate1 .. predicateN)`, |
| 116 | + `(more-> exp1 expr1 .. expN exprN)` where `actual` is threaded through |
| 117 | + each expression `exprX` and checked with the expected value `expX`, |
| 118 | + or `(more-of binding exp1 val1 .. expN valN)` where `actual` is |
| 119 | + destructured using the `binding` and then each expected value `expX` |
| 120 | + is used to check each `valX` -- expressions based on symbols in the |
| 121 | + `binding`." |
101 | 122 | ([a] `(t/is ~a))
|
102 | 123 | ([e a] `(expect ~e ~a true ~e))
|
103 | 124 | ([e a ex?] `(expect ~e ~a ~ex? ~e))
|
|
120 | 141 | (let [form `(~'expect ~e ~a)]
|
121 | 142 | `(let [a# ~(second a)]
|
122 | 143 | (cond (or (sequential? a#) (set? a#))
|
123 |
| - (let [report# t/do-report |
124 |
| - all-reports# (atom nil)] |
| 144 | + (let [all-reports# (atom nil)] |
125 | 145 | (with-redefs [t/do-report (all-report all-reports#)]
|
126 | 146 | (doseq [~'x a#]
|
127 | 147 | ;; TODO: really want x evaluated here!
|
|
135 | 155 | (doseq [r# (:fail @all-reports#)] (t/do-report r#)))))
|
136 | 156 | (map? a#)
|
137 | 157 | (let [e# ~e]
|
138 |
| - (expect e# (select-keys e# (keys a#)) ~ex? ~form)) |
| 158 | + (expect e# (select-keys a# (keys e#)) ~ex? ~form)) |
139 | 159 | :else
|
140 | 160 | (throw (IllegalArgumentException. "'in' requires map or sequence")))))
|
141 | 161 |
|
|
195 | 215 | "Given a name (a symbol that may include metadata) and a test body,
|
196 | 216 | produce a standard 'clojure.test' test var (using 'deftest').
|
197 | 217 |
|
198 |
| - (defexpect name expected actual) is a special case shorthand for |
199 |
| - (defexpect name (expect expected actual)) provided as an easy way to migrate |
| 218 | + `(defexpect name expected actual)` is a special case shorthand for |
| 219 | + `(defexpect name (expect expected actual))` provided as an easy way to migrate |
200 | 220 | legacy Expectation tests to the 'clojure.test' compatibility version."
|
201 | 221 | [n & body]
|
202 | 222 | (if (and (>= 2 (count body))
|
|
205 | 225 | `(t/deftest ~n ~@body)))
|
206 | 226 |
|
207 | 227 | (defmacro expecting
|
208 |
| - "The Expectations version of clojure.test/testing." |
| 228 | + "The Expectations version of `clojure.test/testing`." |
209 | 229 | [string & body]
|
210 | 230 | `(t/testing ~string ~@body))
|
211 | 231 |
|
212 | 232 | ;; DSL functions copied from Expectations:
|
213 |
| -(defmacro side-effects [fn-vec & forms] |
| 233 | +(defmacro side-effects |
| 234 | + "Given a vector of functions to track calls to, execute the body. |
| 235 | +
|
| 236 | + Returns a vector of each set of arguments used in calls to those |
| 237 | + functions. The specified functions will not actually be called: |
| 238 | + only their arguments will be tracked, and the tracking versions of |
| 239 | + those functions will not return useful values (so they should be |
| 240 | + purely side-effecting functions, whose results are not used!)." |
| 241 | + [fn-vec & forms] |
214 | 242 | (when-not (vector? fn-vec)
|
215 | 243 | (throw (IllegalArgumentException.
|
216 | 244 | "side-effects requires a vector as its first argument")))
|
|
227 | 255 | ([^double v ^double d]
|
228 | 256 | (fn [x] (<= (- v (Math/abs d)) x (+ v (Math/abs d))))))
|
229 | 257 |
|
| 258 | +(defn between |
| 259 | + "Given a pair of (numeric) values, return a predicate that expects its |
| 260 | + argument to be be those values or between them -- inclusively." |
| 261 | + [a b] |
| 262 | + (fn [x] (<= a x b))) |
| 263 | + |
| 264 | +(defn between' |
| 265 | + "Given a pair of (numeric) values, return a predicate that expects its |
| 266 | + argument to be (strictly) between those values -- exclusively." |
| 267 | + [a b] |
| 268 | + (fn [x] (< a x b))) |
| 269 | + |
230 | 270 | (defn functionally
|
231 | 271 | "Given a pair of functions, return a custom predicate that checks that they
|
232 | 272 | return the same result when applied to a value. May optionally accept a
|
|
0 commit comments