Matchers

Lemoncheesecake comes with support of matchers, a feature inspired by Hamcrest / PyHamcrest.

The following stock matchers are available:

  • Values:
    • equal_to(expected): check if actual == expected
    • not_equal_to(expected): check if actual != expected
    • greater_than(expected): check if actual > expected
    • greater_than_or_equal_to(expected): check if actual >= expected
    • less_than(expected): check if actual < expected
    • less_than_or_equal_to(expected): check if actual <= expected
    • is_between(min, max): check if actual is between min and max
    • is_none(): check if actual == None
    • is_not_none(): check if actual != None
    • has_length(expected): check if value has expected length (expected can be a value or a Matcher object)
    • is_true(): check if value is a boolean true
    • is_false(): check if value is a boolean false
    • is_json(expected): check is the actual JSON equals expected, if not, the unified diff of actual vs expected is displayed
  • Character strings:
    • starts_with(expected): check if the actual string starts with expected
    • ends_with(expected): check if the actual string ends with expected
    • match_pattern(expected): check if the actual string match expected regexp (expected can be a raw string or an object returned by re.compile())
    • is_text(expected): check is the actual (multi-lined) text equals expected, if not, the unified diff of actual vs expected is displayed
  • Types (expected is optional and can be a value or a matcher object):
    • is_integer([expected]): check if actual is of type int
    • is_float([expected]): check if actual is of type float
    • is_str([expected]): check if actual is of type str (or unicode if Python 2.7)
    • is_dict([expected]): check if actual is of type dict
    • is_list([expected]): check if actual is of type list or tuple
    • is_bool([expected]): check if actual is of type bool
  • Iterable:
    • has_item(expected): check is actual iterable has an element that matches expected (expected can be a value or a Matcher)
    • has_values(expected): check is actual iterable contains at least the expected values
    • has_only_values(expected): check if actual iterable only contains the expected values
    • is_in(expected): check if actual value is among the expected values
  • Dict:
    • has_entry(expected_key [,expected_value]): check if actual dict has expected_key and (optionally) the expected associated value expected_value (which can be a value or a matcher)
  • Logical:
    • is_(expected): return the matcher if expected is a matcher, otherwise wraps expected in the equal_to matcher
    • is_not(expected): make the negation of the expected matcher (or equal_to if the argument is not a matcher)
    • all_of(matcher1, [matcher2, [...]]): check if all the matchers succeed (logical AND between all the matchers)
    • any_of(matcher1, [matcher2, [...]]): check if any of the matchers succeed (logical OR between all the matchers)
    • anything(), something(), existing(): these matchers always succeed whatever the actual value is (only the matcher description changes to fit the matcher’s name)

Those matcher are used by a matching function:

  • check_that(hint, actual, matcher, quiet=False): run the matcher, log the result and return the matching result as a boolean
  • require_that(hint, actual, matcher, quiet=False): run the matcher, log the result and raise an AbortTest exception in case of a match failure
  • assert_that(hint, actual, matcher, quiet=False): run the match, in case of a match failure (and only in this case) log the result and raise an AbortTest exception

The quiet flag can be set to True to hide the matching result details in the report.

The lemoncheesecake.matching module also provides helper functions to ease operations on dict object:

The code:

data = {"foo": 1, "bar": 2}
check_that("data", data, has_entry("foo", equal_to(1)))
check_that("data", data, has_entry("bar", equal_to(2)))

Can be shortened like this:

data = {"foo": 1, "bar": 2}
check_that_entry("foo", equal_to(1), in_=data)
check_that_entry("bar", equal_to(2), in_=data)

check_that_entry can also be used with the context manager this_dict:

with this_dict({"foo": 1, "bar": 2}):
    check_that_entry("foo", equal_to(1))
    check_that_entry("bar", equal_to(2))

check_that_in can conveniently be used instead of this_dict + check_that_entry when the context manager block is only composed of calls to check_that_entry:

check_that_in(
    {"foo": 1, "bar": 2},
    "foo", equal_to(1),
    "bar", equal_to(2)
)

The same dict helper counter parts are available for require_that and assert_that:

  • require_that_entry and require_that_in
  • assert_that_entry and assert_that_in

If one match fails in a test, this test will be marked as failed.