Closed viebel closed 6 years ago
This question is sorta similar to https://github.com/marick/Midje/issues/405#issue-266243572; wanted to link them so that the context from the two issues can be shared.
As far as I know, wrapping each level with a check is the way to do it currently.
That said, a colleague and I are working on building a matcher-combinator library that can be used with midje and will do this wrapping automatically so that you can write tests like
(fact {:a {:b 1}} => (embeds {:a {:b (roughly 1.0)}})
Since this has been requested a bunch and we actually use a similar, but hacky approach a lot within our organization, this is going to be the next midje feature I prioritize :)
That will be great.
To follow up on this, we've released a new library for checking nested data-structures that attempts to solve the problem described here: https://github.com/nubank/matcher-combinators
Using it with midje, you can write
(require '[midje.sweet :refer :all]
'[matcher-combinators.matchers :refer [equals embeds]]
'[matcher-combinators.midje :refer [match]])
(fact
{:a {:b 1}} => (match {:a {:b (roughly 1.0)}}))
which is equivalent to
(fact
{:a {:b 1}} => (contains {:a (contains {:b (roughly 1.0)})}))
And to do exactly
(fact
{:a {:b 1}} => (just {:a (just {:b (roughly 1.0)})}))
with matcher-combinators you still need to wrap the nested maps with the strict equals
matcher because the default matcher for maps is a looser embeds
(similar to midje's contains
)
(fact
{:a {:b 1}} => (match (equals {:a (equals {:b (roughly 1.0)})})))
matcher-combinators
also give you nice diff messages when there are mismatches in results and can also be used in other test frameworks.
closing this out given that the matcher-combinators
library solves the issue and is integrated with midje.
Sorry, I closed it before offering a satisfactory solution to your exact problem via matcher-combinators
.
Good news is that I have a PR open that implements what you are looking for: https://github.com/nubank/matcher-combinators/pull/29
When that gets merged/released you can do something like
(fact
{:a {:b 1}} => (matcher-combinators.midje/match-equals {:a {:b (roughly 0.95)}}))
or even define your own matcher like this
(midje.checking.checkers.defining/defchecker my-matcher [matcher]
(let [delta 0.1]
(matcher-combinators.midje/match-with
{:number (fn [exp] (matcher-combinators.core/->Roughly delta exp))
:map (fn [exp] (matcher-combinators.core/->EqualsMap exp))}
matcher)))
;; ---
(fact
{:a {:b 1}} => (my-matcher {:a {:b 0.95}}))
thanks for the updtae @phillipm
How can we check a nested map with
roughly
This doesn't work:
But this works:
Is there a simpler way?