-
Notifications
You must be signed in to change notification settings - Fork 129
Checking maps and records
Using a map on the right-hand side of a prediction means you care about contents, not type:
(defrecord R [x y])
(fact
;; That the left-hand side below is a record is irrelevant:
(R. 1 2) => {:x 1, :y 2}
;; The contents of the left are compared to the right in exactly
;; the same way as if both sides were maps:
{:x 1, :y 2} => {:x 1, :y 2})
When testing code that generates records, you may require that the result be one of those records, not, say, some random map:
(fact "using a record on the right implies that you care about *both* contents and type"
{:x 1, :y 2} =not=> (R. 1 2)
(NotR. 1 2) =not=> (R. 1 2)
(R. 1 2) => (R. 1 2)))
Use just
if you want a more flexible check of values than equality. For example:
(fact "`just` provides extended equality"
{:a 1, :b 2, :c "some text"} => (just {:a odd?, :b 2, :c #"text"}))
Use contains
when you don't care about parts of a map or record:
(fact "contains ignores unmentioned keys"
(R. 1 'IGNORE!) => (contains {:x 1}))
contains
also provides extended equality:
(fact "`contains` provides extended equality"
(R. 1 'IGNORE) => (contains {:x odd?}))
In both of the previous examples, contains
will ignore the type of the left-hand size. If you want to say specifically that the left-hand side is an R
that contains an odd :x
, use a combining checker:
(fact
(R. 1 'IGNORE!) => (every-checker #(instance? R %)
(contains {:x 1})))
has
lets you make quantified ("every" "some") claims about the values of a map or record:
(fact "`'has` quantifies over values"
{:a 1, :b 3} => (has every? odd?))
Making claims about keys is more awkward:
(fact "ways to make claims about keys"
(keys {:x 1, :y 1}) => (just #{:x :y}) ;; Contains every key
{:x 1, :y 1} => (just {:x anything, :y anything}) ;; a variant
(keys {:x 1, :y 1}) => (contains #{:x}) ;; Contains some of the keys
{:x 1, :y 1} => (contains {:x anything}))
The just
and contains
right-hand sides can take arrays of pairs (or Java MapEntry
objects) instead of a map or record:
(fact "a sequence of key/value pairs is OK on the right-hand side"
{:a 1, :b 2} => (just [[:a 1] [:b 2]])
(R. 1 nil) => (contains [[:x 1]]))