Why pyhamcrest is failing contains() matcher for list of 2 or more dicts, but works fine with list of 1 dict?
What is the best way to write hamcrest (pyhamcrest) matcher for list of dicts?
First test passed, second failed in this unittest example.
import unittest
from hamcrest import contains, assert_that, has_entries
class ContainsTest(unittest.TestCase):
dict1, dict2 = {"a": 1, "b": 2}, {"a": 1, "b": 2}
sequence1, sequence2 = list(), list()
sequence1.append(dict1)
sequence2.append(dict1)
sequence2.append(dict2)
@staticmethod
def test_sequence():
assert_that(ContainsTest.sequence1, contains(has_entries({'a': 1, 'b': 2})))
assert_that(ContainsTest.sequence2, contains(has_entries({'a': 1, 'b': 2})))
if __name__ == "__main__":
ContainsTest.test_sequence()
Unittest output:
File "/usr/local/lib/python3.6/site-packages/hamcrest/core/assert_that.py",
line 57, in _assert_match raise AssertionError(description)
AssertionError:
Expected: a sequence containing [a dictionary containing {'a': <1>, 'b': <2>}]
but: Not matched: <{'a': 1, 'b': 2}>
Ran 1 test in 0.027s
FAILED (failures=1)
Process finished with exit code 1
You're looking for has_item
, not contains
.
Somewhat confusingly, PyHamcrest's contains
isn't a containment check in the sense of the __contains__
magic method. Its semantics are modeled after the original Hamcrest's contains
matcher. It's not testing if some element of the list matches the given matcher; it wants a separate matcher for each list element, and it'll apply matchers to corresponding elements of the list. has_item
is the one that checks if some item matches.
Quoting the docs:
Matches if sequence’s elements satisfy a given list of matchers, in order.
Parameters: match1,... – A comma-separated list of matchers.
This matcher iterates the evaluated sequence and a given list of matchers, seeing if each element satisfies its corresponding matcher.Any argument that is not a matcher is implicitly wrapped in an equal_to matcher to check for equality.
You've provided one matcher for a list of two elements. PyHamcrest wants two matchers. The second dict isn't getting matched.