=?This adds a new test expression type =? that uses a Methodical multimethod
to decide whether expected and actual should be "approximately equal". It dispatches on the types of expected
and actual.
Now while you can already write all the sort of "approximately equal" things you want in theory using schema= (defined
in mb.hawk.assert-exprs, in practice it's a
bit of a hassle. Want to convert an = to schema= and change one key in a map to use s/Int instead of a specific
number? Have fun wrapping every other value in s/eq. Want to ignore unused keys like partial=? You need to stick
s/Keyword s/Any in every. single. map. =? takes the best of schema= and partial=, steals a few ideas from
Expectations, and is more powerful and easier to use than any of
those three.
= usages can be replaced with =? with no other changes -- you can replace that one single key with a predicate
function and leave everything else the same.
Here's some rules I've defined already:
Two regex patterns that are the exact same pattern should be considered =?. (For some wacko reason regex patterns aren't equal unless they're the same object)
An expected plain Clojure map should be approximately equal to an actual record type. We shouldn't need some
hack like mt/derecordize to be able to write tests for this stuff
an expected regex pattern should be approximately equal to an actual string if the string matches the
regex. (This is what re= currently does. We can replace re= with =? entirely.)
an expected function should be approximately equal to a an actual value if (expected actual) returns truthy.
an expected map should be approximately equal to an actual map if all the keys in expected are present in
actual and their respective values are approximately equal. In other words, extra keys in actual should be
ignored (this is what our partial= works)
Motivating example: two sublcasses of Temporal e.g. OffsetDateTime and ZonedDateTime should be =? if we
would print them exactly the same way.
Defining new =? behaviors is as simple as writing a new defmethod.
(methodical/defmethod =?-diff [java.util.regex.Pattern String]
[expected-regex s]
(when-not (re-matches expected-regex s)
(list 'not (list 're-matches expected-regex s))))
Methods are expected to return nil if things are approximately equal, or a form explaining why they aren't if they
aren't. In this case, it returns something like
(not (re-matches #"\d+cans" "toucans")))
This is printed in the correct place by humanized test output and other things that can print diffs.
=? behaviors:Built-in functions for =? are defined in the mb.hawk.assert-exprs.approximately-equal namespace. You can create
an alias for this namespace like so:
(require '[mb.hawk.assert-exprs.approximately-equal :as =?])
exactlyexactly means results have to be exactly equal as if by =. Use this to get around the normal way =? would
compare things. This works inside collections as well.
(is (=? {:m (=?/exactly {:a 1})}
{:m {:a 1, :b 2}}))
;; =>
expected: {:m (exactly {:a 1})}
actual: {:m {:a 1, :b 2}}
diff: - {:m (not (= (exactly {:a 1}) {:a 1, :b 2}))}
+ nil
schemaschema compares things to a schema.core Schema:
(is (=? {:a 1, :b (=?/schema {s/Keyword s/Int})}
{:a 1, :b {:c 2}}))
=> ok
(is (=? {:a 1, :b (=?/schema {s/Keyword s/Int})}
{:a 1, :b {:c 2.0}}))
=>
expected: {:a 1, :b (schema {(pred keyword?) (pred integer?)})}
actual: {:a 1, :b {:c 2.0}}
diff: - {:b {:c (not (integer? 2.0))}}
+ nil
mallimalli compares things to a malli schema:
(is (=? {:a 1, :b (=?/malli [:map-of :keyword :int])}
{:a 1, :b {:c 2}}))
=> ok
(is (=? {:a 1, :b (=?/malli [:map-of :keyword :int])}
{:a 1, :b {:c 2.0}}))
=>
expected: {:a 1, :b (malli [:map-of :keyword :int])}
actual: {:a 1, :b {:c 2.0}}
diff: - {:b {:c ["should be an integer"]}}
approxapprox compares whether two numbers are approximately equal:
;; is the difference between actual and 1.5 less than ±0.1?
(is (=? (=?/approx [1.5 0.1])
1.51))
=> true
(is (=? (=?/approx [1.5 0.1])
1.6))
=>
expected: (approx [1.5 0.1])
actual: 1.6
diff: - (not (approx 1.5 1.6 #_epsilon 0.1))
+ nil
Can you improve this documentation? These fine people already did:
Cam Saul, Cal Herries & Ngoc KhuatEdit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |