hamcrest / PyHamcrest

Hamcrest matchers for Python
http://hamcrest.org/
Other
773 stars 112 forks source link

has_entry with nested matchers does not report excact cause #156

Closed dz0 closed 1 year ago

dz0 commented 3 years ago

Hi, simple example

data = {'level1': {'level2': 2}}
matcher_level2 = has_entries({'level2': 42})

Why has_entry does not display (block) deeper cause?:

assert_that(data, has_entry('level1', matcher_level2))


Expected: a dictionary containing ['level1': a dictionary containing {'level2': <42>}]
but: was <{'level1': {'level2': 2}}>

As  `has_entries` displays deepest cause: 

> assert_that(data['level1'], matcher_level2) 

Expected: a dictionary containing {'level2': <42>} but: value for 'level2' was <2>


> assert_that(data, has_entries({'level1': matcher_level2}))

Expected: a dictionary containing {'level1': a dictionary containing {'level2': <42>}} but: value for 'level1' value for 'level2' was <2>

dz0 commented 3 years ago

ps.: I'd expect has_entry to be as

def has_entry(key, value_match):
    return has_entries({key: value_match})
brunns commented 3 years ago

Not quite that simple - has_entry() allows a matcher for the key as well as for the value. I'll take a look when I have some time.

brunns commented 3 years ago

Thinking about it, perhaps that's why has_entry() doesn't give better mismatch messages. Imagine that the key was specified as hamcrest.anything() - how should the message read then?

Still, if the key matched exactly once, we could probably give better messages in that special but common case.

brunns commented 3 years ago

Does https://github.com/hamcrest/PyHamcrest/pull/157 look any good, @dz0 and @offbyone?

brunns commented 1 year ago

This fix has been merged & released.