|
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