Skip to content

Commit

Permalink
Fix for #156 - if has_entry() has only a single matching key, report …
Browse files Browse the repository at this point in the history
…the mismatching value.
  • Loading branch information
brunns authored and offbyone committed Mar 6, 2021
1 parent 02cf6ac commit bbd147d
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
20 changes: 19 additions & 1 deletion src/hamcrest/library/collection/isdict_containing.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Hashable, Mapping, TypeVar, Union
from typing import Hashable, Mapping, MutableMapping, TypeVar, Union

from hamcrest.core.base_matcher import BaseMatcher
from hamcrest.core.description import Description
Expand Down Expand Up @@ -32,6 +32,24 @@ def describe_to(self, description: Description) -> None:
self.key_matcher
).append_text(": ").append_description_of(self.value_matcher).append_text("]")

def describe_mismatch(self, item: Mapping[K, V], mismatch_description: Description) -> None:
key_matches: MutableMapping[K, V] = {}
if hasmethod(item, "items"):
for key, value in item.items():
if self.key_matcher.matches(key):
key_matches[key] = value
if len(key_matches) == 1:
key, value = key_matches.popitem()
mismatch_description.append_text("value for ").append_description_of(key).append_text(
" "
)
self.value_matcher.describe_mismatch(value, mismatch_description)
else:
super().describe_mismatch(item, mismatch_description)

def describe_match(self, item: Mapping[K, V], match_description: Description) -> None:
super().describe_match(item, match_description)


def has_entry(
key_match: Union[K, Matcher[K]], value_match: Union[V, Matcher[V]]
Expand Down
15 changes: 14 additions & 1 deletion tests/hamcrest_unit_test/collection/isdict_containing_test.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import unittest

from hamcrest import starts_with
from hamcrest.core.core.isequal import equal_to
from hamcrest.library.collection.isdict_containing import has_entry
from hamcrest_unit_test.matcher_test import MatcherTest
from hamcrest_unit_test.matcher_test import MatcherTest, assert_mismatch_description

from .quasidict import QuasiDictionary

Expand Down Expand Up @@ -40,6 +41,18 @@ def testMismatchDescriptionShowsActualArgument(self):
def testDescribeMismatch(self):
self.assert_describe_mismatch("was 'bad'", has_entry("a", 1), "bad")

def test_describe_single_matching_key_mismatching_value(self):
assert_mismatch_description("value for 'a' was <2>", has_entry("a", 1), {"a": 2})
assert_mismatch_description(
"value for 'aa' was <2>", has_entry(starts_with("a"), 1), {"aa": 2}
)
assert_mismatch_description(
"was <{'ab': 2, 'ac': 3}>", has_entry(starts_with("a"), 1), {"ab": 2, "ac": 3}
)

# def test_describe_match(self):
# assert_match_description("value for 'a' was <1>", has_entry("a", 1), {"a": 1})


if __name__ == "__main__":
unittest.main()

0 comments on commit bbd147d

Please sign in to comment.