Working on the matches() function

This commit is contained in:
2025-10-25 00:31:07 +02:00
parent 06aff27cad
commit 847684a15b
3 changed files with 150 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
class Predicate:
def validate(self, actual):
raise NotImplementedError
class StartsWith(Predicate):
def __init__(self, value):
self.value = value
def validate(self, actual):
return actual.startswith(self.value)
def __str__(self):
return f"StartsWith({self.value})"
class Contains(Predicate):
def __init__(self, value):
self.value = value
def validate(self, actual):
return self.value in actual
def __str__(self):
return f"Contains({self.value})"
class DoesNotContain(Predicate):
def __init__(self, value):
self.value = value
def validate(self, actual):
return self.value not in actual
def __str__(self):
return f"DoesNotContain({self.value})"
def matches(actual, expected, path=""):
def print_path(p):
return f"Path '{p}':\n\t" if p else ""
def _type(x):
return type(x)
def _debug(elt):
return str(elt) if elt else "None"
def _debug_compare(a, b):
return f"actual={_debug(a)}, expected={_debug(b)}"
def _error_msg(msg, _actual=None, _expected=None):
if _actual is None and _expected is None:
debug_info = ""
elif _actual is None:
debug_info = _debug(_expected)
elif _expected is None:
debug_info = _debug(_actual)
else:
debug_info = _debug_compare(_actual, _expected)
return f"{print_path(path)}\n{msg} : {debug_info}"
def _assert_error(msg, _actual=None, _expected=None):
assert False, _error_msg(msg, _actual=_actual, _expected=_expected)
if actual is not None and expected is None:
_assert_error("Actual is not None while expected is None", _actual=actual)
if actual is None and expected is not None:
_assert_error("Actual is None while expected is ", _expected=expected)
assert _type(actual) == _type(expected) or (hasattr(actual, "tag") and hasattr(expected, "tag")), \
_assert_error("The types are different: ", _actual=actual, _expected=expected)
if isinstance(expected, (list, tuple)):
if len(actual) < len(expected):
_assert_error("Actual is smaller than expected: ", _actual=actual, _expected=expected)
if len(actual) > len(expected):
_assert_error("Actual is bigger than expected: ", _actual=actual, _expected=expected)
for actual_child, expected_child in zip(actual, expected):
assert matches(actual_child, expected_child, path=path)
elif hasattr(expected, "tag"):
assert actual.tag == expected.tag, _error_msg("The elements are different: ",
_actual=actual.tag,
_expected=expected.tag)
for expected_attr, expected_value in expected.attrs.items():
assert expected_attr in actual.attrs, _error_msg(f"'{expected_attr}' is not found in Actual:",
_actual=actual.attrs)
if isinstance(expected_value, Predicate):
assert expected_value.validate(actual.attrs[expected_attr]), \
_error_msg(f"The condition '{expected_value}' is not satisfied: ",
_actual=actual.attrs[expected_attr],
_expected=expected_value)
else:
assert actual.attrs[expected_attr] == expected.attrs[expected_attr], \
_error_msg(f"The values are different for '{expected_attr}': ",
_actual=actual.attrs[expected_attr],
_expected=expected.attrs[expected_attr])
return True