|
31 | 31 | (defmacro more-> [& _] (bad-usage "more->"))
|
32 | 32 | (defmacro more [& _] (bad-usage "more"))
|
33 | 33 |
|
| 34 | +(defn spec? [e] |
| 35 | + (and (keyword? e) |
| 36 | + (try |
| 37 | + (require 'clojure.spec.alpha) |
| 38 | + (when-let [get-spec (resolve 'clojure.spec.alpha/get-spec)] |
| 39 | + (boolean (get-spec e))) |
| 40 | + (catch Throwable _)))) |
| 41 | + |
34 | 42 | ;; smart equality extension to clojure.test assertion -- if the expected form
|
35 | 43 | ;; is a predicate (function) then the assertion is equivalent to (is (e a))
|
36 | 44 | ;; rather than (is (= e a)) and we need the type check done at runtime, not
|
37 | 45 | ;; as part of the macro translation layer
|
38 | 46 | (defmethod t/assert-expr '=? [msg form]
|
39 | 47 | ;; (is (=? val-or-pred expr))
|
40 |
| - (let [[_ e a] form] |
| 48 | + (let [[_ e a] form |
| 49 | + conform? (spec? e) |
| 50 | + valid? (when conform? (resolve 'clojure.spec.alpha/valid?)) |
| 51 | + explain-str? (when conform? (resolve 'clojure.spec.alpha/explain-str))] |
41 | 52 | `(let [e# ~e
|
42 | 53 | a# ~a
|
43 |
| - r# (if (fn? e#) (e# a#) (= e# a#)) |
44 |
| - humane?# (and humane-test-output? (not (fn? e#)))] |
| 54 | + r# (cond ~conform? |
| 55 | + (~valid? e# a#) |
| 56 | + (fn? e#) |
| 57 | + (e# a#) |
| 58 | + :else |
| 59 | + (= e# a#)) |
| 60 | + humane?# (and humane-test-output? (not (fn? e#)) (not ~conform?))] |
45 | 61 | (if r#
|
46 | 62 | (t/do-report {:type :pass, :message ~msg,
|
47 | 63 | :expected '~form, :actual (if (fn? e#)
|
48 | 64 | (list '~e a#)
|
49 | 65 | a#)})
|
50 |
| - (t/do-report {:type :fail, :message ~msg, |
| 66 | + (t/do-report {:type :fail, :message (if ~conform? |
| 67 | + (~explain-str? e# a#) |
| 68 | + ~msg) |
51 | 69 | :diffs (if humane?#
|
52 | 70 | [[a# (take 2 (data/diff e# a#))]]
|
53 | 71 | [])
|
|
64 | 82 | "Wrapper for forms that might throw an exception so exception class names
|
65 | 83 | can be used as predicates. This is only needed for more-> so that you can
|
66 | 84 | thread exceptions into code that can parse information out of them, to be
|
67 |
| - used with various expect predicates. |
68 |
| -
|
69 |
| - TODO: revisit this to see if wrapping the whole expect with try/catch will |
70 |
| - allow this to be omitted." |
| 85 | + used with various expect predicates." |
71 | 86 | [form]
|
72 | 87 | `(try ~form (catch Throwable t# t#)))
|
73 | 88 |
|
|
82 | 97 | (swap! store update (:type m) (fnil conj []) m)))
|
83 | 98 |
|
84 | 99 | (defmacro expect
|
85 |
| - "Translate Expectations DSL to clojure.test language. |
86 |
| -
|
87 |
| - Things implemented so far: |
88 |
| - * simple predicate test |
89 |
| - * class test |
90 |
| - * exception test |
91 |
| - * regex test |
92 |
| - * simple equality |
93 |
| - * from-each actual |
94 |
| - * in actual |
95 |
| - * more-of expected |
96 |
| - * more-> expected |
97 |
| - * more expected |
98 |
| - * side-effects (copied from Expectations) |
99 |
| -
|
100 |
| - Things to implement: |
101 |
| - * redef-state ? |
102 |
| - * freeze-time |
103 |
| - * context / in-context ?" |
| 100 | + "Translate Expectations DSL to clojure.test language." |
104 | 101 | ([a] `(t/is ~a))
|
105 | 102 | ([e a] `(expect ~e ~a true ~e))
|
106 | 103 | ([e a ex?] `(expect ~e ~a ~ex? ~e))
|
|
0 commit comments