def starts_with_matches_when_actual_string_starts_with_value_passed_to_matcher(): matcher = starts_with("ab") assert_equal(matched(), matcher.match("ab")) assert_equal(matched(), matcher.match("abc")) assert_equal(matched(), matcher.match("abcd")) assert_equal(unmatched("was 'a'"), matcher.match("a")) assert_equal(unmatched("was 'cab'"), matcher.match("cab"))
def match(self, actual): if self._name not in actual: return unmatched("was missing value '{0}'".format(self._name)) else: actual_value = actual.get(self._name) property_result = self._matcher.match(actual_value) if property_result.is_match: return matched() else: return unmatched("value '{0}' {1}".format( self._name, property_result.explanation))
def match(self, item): actual = self._get_value(item, self._path) if actual: result = self.matcher.match(actual) if result.is_match: return result else: explanation = "property {} {}".format(self.readable_path(), result.explanation) return unmatched(explanation) else: return unmatched("had no property {}".format(self.readable_path()))
def does_not_match_when_value_does_not_match(): matcher = is_mapping({"a": equal_to(1), "b": equal_to(2)}) assert_equal(unmatched("value for key 'b' mismatched:\n * was 3"), matcher.match({ "a": 1, "b": 3 }))
def mismatches_when_actual_is_not_iterable(): matcher = includes(equal_to("apple")) assert_equal( unmatched("was not iterable\nwas 0"), matcher.match(0) )
def mismatches_when_actual_is_not_iterable(): matcher = all_elements(equal_to("apple")) assert_equal( unmatched("was not iterable\nwas 0"), matcher.match(0) )
def mismatches_when_contains_extra_item(): matcher = contains_exactly(equal_to("apple")) assert_equal( unmatched("had extra elements:\n * 'coconut'"), matcher.match(["coconut", "apple"]) )
def mismatches_when_item_is_expected_but_iterable_is_empty(): matcher = contains_exactly(equal_to("apple")) assert_equal( unmatched("iterable was empty"), matcher.match([]) )
def mismatches_when_item_is_missing(): matcher = contains_exactly(equal_to("apple"), equal_to("banana"), equal_to("coconut")) assert_equal( unmatched("was missing element:\n * 'banana'\nThese elements were in the iterable, but did not match the missing element:\n * 'coconut': was 'coconut'\n * 'apple': already matched"), matcher.match(["coconut", "apple"]) )
def mismatches_when_actual_is_not_iterable(): matcher = contains_exactly() assert_equal( unmatched("was not iterable\nwas 0"), matcher.match(0) )
def mismatches_when_item_is_missing(): matcher = is_sequence(equal_to("apple"), equal_to("banana"), equal_to("coconut")) assert_equal( unmatched("element at index 2 was missing"), matcher.match(["apple", "banana"]) )
def mismatches_when_items_are_in_wrong_order(): matcher = is_sequence(equal_to("apple"), equal_to("banana")) assert_equal( unmatched("element at index 0 mismatched:\n * was 'banana'"), matcher.match(["banana", "apple"]) )
def mismatches_when_duplicate_is_missing(): matcher = includes(equal_to("apple"), equal_to("apple")) assert_equal( unmatched( "was missing element:\n * 'apple'\nThese elements were in the iterable, but did not match the missing element:\n * 'apple': already matched" ), matcher.match(["apple"]))
def mismatches_when_item_in_iterable_does_not_match(): matcher = all_elements(equal_to("apple")) assert_equal( unmatched("element at index 1 mismatched: was 'orange'"), matcher.match(["apple", "orange"]) )
def submatcher_is_coerced_to_matcher(): matcher = has_attrs(username="******") assert_equal( unmatched("attribute username was 'bobbity'"), matcher.match(User("bobbity", None)) )
def mismatches_when_item_is_missing(): matcher = includes(equal_to("apple"), equal_to("banana"), equal_to("coconut")) assert_equal( unmatched("was missing element:\n * 'banana'\nThese elements were in the iterable, but did not match the missing element:\n * 'coconut': was 'coconut'\n * 'apple': already matched"), matcher.match(["coconut", "apple"]) )
def mismatches_when_item_is_expected_but_iterable_is_empty(): matcher = includes(equal_to("apple")) assert_equal( unmatched("iterable was empty"), matcher.match([]) )
def mismatches_when_duplicate_is_missing(): matcher = includes(equal_to("apple"), equal_to("apple")) assert_equal( unmatched("was missing element:\n * 'apple'\nThese elements were in the iterable, but did not match the missing element:\n * 'apple': already matched"), matcher.match(["apple"]) )
def contains_string_matches_when_actual_string_contains_value_passed_to_matcher(): matcher = contains_string("ab") assert_equal(matched(), matcher.match("ab")) assert_equal(matched(), matcher.match("abc")) assert_equal(matched(), matcher.match("abcd")) assert_equal(matched(), matcher.match("cabd")) assert_equal(matched(), matcher.match("cdab")) assert_equal(unmatched("was 'a'"), matcher.match("a"))
def close_to_matches_when_actual_is_close_to_value_plus_delta(): matcher = close_to(42, 1) assert_equal(matched(), matcher.match(43)) assert_equal(matched(), matcher.match(42.5)) assert_equal(matched(), matcher.match(42)) assert_equal(matched(), matcher.match(41.5)) assert_equal(matched(), matcher.match(41)) assert_equal(unmatched("was 40 (2 away from 42)"), matcher.match(40))
def mismatches_when_submatcher_mismatches(): matcher = all_of( has_attr("username", equal_to("bob")), has_attr("email_address", equal_to("*****@*****.**")), ) assert_equal(unmatched("was missing attribute username"), matcher.match("bobbity"))
def does_not_match_when_there_are_extra_keys(): matcher = is_mapping({"a": equal_to(1)}) assert_equal(unmatched("had extra keys:\n * 'b'\n * 'c'"), matcher.match({ "a": 1, "b": 1, "c": 1 }))
def mismatches_when_property_is_missing(): matcher = has_attrs( ("username", equal_to("bob")), ("email_address", equal_to("*****@*****.**")), ) assert_equal(unmatched("was missing attribute username"), matcher.match("bobbity"))
def close_to_matches_when_actual_is_close_to_value_plus_delta(): matcher = close_to(42, 1) assert_equal(matched(), matcher.match(43)) assert_equal(matched(), matcher.match(42.5)) assert_equal(matched(), matcher.match(42)) assert_equal(matched(), matcher.match(41.5)) assert_equal(matched(), matcher.match(41)) assert_equal(unmatched("was 40 (2 away from 42)"), matcher.match(40))
def explanation_of_mismatch_contains_mismatch_of_property(): matcher = has_attrs( username=equal_to("bob"), email_address=equal_to("*****@*****.**"), ) assert_equal( unmatched("attribute email_address was '*****@*****.**'"), matcher.match(User("bob", "*****@*****.**")))
def contains_string_matches_when_actual_string_contains_value_passed_to_matcher( ): matcher = contains_string("ab") assert_equal(matched(), matcher.match("ab")) assert_equal(matched(), matcher.match("abc")) assert_equal(matched(), matcher.match("abcd")) assert_equal(matched(), matcher.match("cabd")) assert_equal(matched(), matcher.match("cdab")) assert_equal(unmatched("was 'a'"), matcher.match("a"))
def mismatches_when_no_submatchers_match(): matcher = any_of( equal_to("bob"), equal_to("jim"), ) assert_equal( unmatched("did not match any of:\n * 'bob' [was 'alice']\n * 'jim' [was 'alice']"), matcher.match("alice"), )
def close_to_matches_datetime_values(): matcher = close_to(datetime(2018, 1, 17), timedelta(days=1)) assert_equal(matched(), matcher.match(datetime(2018, 1, 18))) assert_equal(matched(), matcher.match(datetime(2018, 1, 17))) assert_equal(matched(), matcher.match(datetime(2018, 1, 16))) assert_equal(unmatched( "was datetime.datetime(2018, 1, 15, 0, 0) (datetime.timedelta(2) away from datetime.datetime(2018, 1, 17, 0, 0))" ), matcher.match(datetime(2018, 1, 15)) )
def mismatches_when_property_is_missing(): matcher = has_attrs( ("username", equal_to("bob")), ("email_address", equal_to("*****@*****.**")), ) assert_equal( unmatched("was missing attribute username"), matcher.match("bobbity") )
def explanation_of_mismatch_contains_mismatch_of_property(): matcher = has_attrs( username=equal_to("bob"), email_address=equal_to("*****@*****.**"), ) assert_equal( unmatched("attribute email_address was '*****@*****.**'"), matcher.match(User("bob", "*****@*****.**")) )
def mismatches_when_no_submatchers_match(): matcher = any_of( equal_to("bob"), equal_to("jim"), ) assert_equal( unmatched( "did not match any of:\n * 'bob' [was 'alice']\n * 'jim' [was 'alice']" ), matcher.match("alice"), )
def close_to_matches_any_types_supporting_comparison_and_addition_and_subtraction( ): class Instant(object): def __init__(self, seconds_since_epoch): self.seconds_since_epoch = seconds_since_epoch def __sub__(self, other): if isinstance(other, Instant): return Interval(self.seconds_since_epoch - other.seconds_since_epoch) else: return NotImplemented def __repr__(self): return "Instant({})".format(self.seconds_since_epoch) @functools.total_ordering class Interval(object): def __init__(self, seconds): self.seconds = seconds def __abs__(self): return Interval(abs(self.seconds)) def __eq__(self, other): if isinstance(other, Interval): return self.seconds == other.seconds else: return NotImplemented def __lt__(self, other): if isinstance(other, Interval): return self.seconds < other.seconds else: return NotImplemented def __repr__(self): return "Interval({})".format(self.seconds) matcher = close_to(Instant(42), Interval(1)) assert_equal(matched(), matcher.match(Instant(43))) assert_equal(matched(), matcher.match(Instant(42.5))) assert_equal(matched(), matcher.match(Instant(42))) assert_equal(matched(), matcher.match(Instant(41.5))) assert_equal(matched(), matcher.match(Instant(41))) assert_equal( unmatched("was Instant(40) (Interval(2) away from Instant(42))"), matcher.match(Instant(40)))
def match(self, item): assert callable(item), "The actual value is not callable." @retrying.retry( wait_fixed=self._wait_fixed, stop_max_attempt_number=self._max_attempts, retry_on_exception=common.ignore_exception, retry_on_result=lambda r: r.is_match is not True) def try_match(): actual = item() return self._matcher.match(actual) try: return try_match() except retrying.RetryError as e: explanation = "after {} retries {}".format(e.last_attempt.attempt_number, e.last_attempt.value.explanation) return unmatched(explanation)
def match(self, item): assert callable(item), "The actual value is not callable." @retrying.retry(wait_fixed=self._wait_fixed, stop_max_attempt_number=self._max_attempts, retry_on_exception=common.ignore_exception, retry_on_result=lambda r: r.is_match is not True) def try_match(): actual = item() return self._matcher.match(actual) try: return try_match() except retrying.RetryError as e: explanation = "after {} retries {}".format( e.last_attempt.attempt_number, e.last_attempt.value.explanation) return unmatched(explanation)
def does_not_match_when_there_are_extra_keys(): matcher = is_mapping({"a": equal_to(1)}) assert_equal(unmatched("had extra keys:\n * 'b'\n * 'c'"), matcher.match({"a": 1, "b": 1, "c": 1}))
def does_not_match_when_keys_are_missing(): matcher = is_mapping({"a": equal_to(1), "b": equal_to(2)}) assert_equal(unmatched("was missing key: 'b'"), matcher.match({"a": 1}))
def mismatches_when_property_is_missing(): assert_equal( unmatched("was missing attribute username"), has_attr("username", equal_to("bob")).match("bobbity") )
def mismatches_when_no_exception_is_raised(): matcher = raises(is_instance(KeyError)) assert_equal(unmatched("did not raise exception"), matcher.match(lambda: None))
def mismatches_when_value_is_not_callable(): matcher = raises(is_instance(ValueError)) assert_equal(unmatched("was not callable"), matcher.match(42))
def mismatches_when_items_are_in_wrong_order(): matcher = is_sequence(equal_to("apple"), equal_to("banana")) assert_equal(unmatched("element at index 0 mismatched:\n * was 'banana'"), matcher.match(["banana", "apple"]))
def submatcher_is_coerced_to_matcher(): matcher = has_feature("name", lambda user: user.username, "bob") assert_equal(unmatched("name: was 'bobbity'"), matcher.match(User("bobbity")))
def explanation_of_mismatch_contains_mismatch_of_feature(): matcher = has_feature("name", lambda user: user.username, equal_to("bob")) assert_equal(unmatched("name: was 'bobbity'"), matcher.match(User("bobbity")))
def mismatches_when_feature_extraction_fails(): # TODO: return matcher = has_feature("name", lambda user: user.username, equal_to("bob")) assert_equal(unmatched(""), matcher.match("bobbity"))
def submatcher_is_coerced_to_matcher(): assert_equal( unmatched("attribute username was 'bobbity'"), has_attr("username", "bob").match(User("bobbity")) )
def explanation_of_mismatch_contains_mismatch_of_property(): assert_equal( unmatched("attribute username was 'bobbity'"), has_attr("username", equal_to("bob")).match(User("bobbity")) )
def explanation_of_mismatch_contains_actual_type(): assert_equal(unmatched("had type float"), is_instance(int).match(1.0))
def mismatches_when_item_is_missing(): matcher = is_sequence(equal_to("apple"), equal_to("banana"), equal_to("coconut")) assert_equal(unmatched("element at index 2 was missing"), matcher.match(["apple", "banana"]))
def explanation_of_mismatch_contains_mismatch_of_property(): assert_equal(unmatched("attribute username was 'bobbity'"), has_attr("username", equal_to("bob")).match(User("bobbity")))
def does_not_match_when_negated_matcher_matches(): assert_equal(unmatched("matched: 1"), not_(equal_to(1)).match(1))
def mismatches_when_property_is_missing(): assert_equal(unmatched("was missing attribute username"), has_attr("username", equal_to("bob")).match("bobbity"))
def does_not_match_when_keys_are_missing(): matcher = is_mapping({"a": equal_to(1), "b": equal_to(2)}) assert_equal(unmatched("was missing key: 'b'"), matcher.match({"a": 1}))
def does_not_match_when_value_does_not_match(): matcher = is_mapping({"a": equal_to(1), "b": equal_to(2)}) assert_equal(unmatched("value for key 'b' mismatched:\n * was 3"), matcher.match({"a": 1, "b": 3}))
def explanation_of_mismatch_contains_repr_of_actual(): assert_equal(unmatched("was 2"), equal_to(1).match(2)) assert_equal(unmatched("was 'hello'"), equal_to(1).match("hello"))
def submatcher_is_coerced_to_matcher(): assert_equal(unmatched("attribute username was 'bobbity'"), has_attr("username", "bob").match(User("bobbity")))