enhance excinfo.match failure output

* now multiline and compares regexes
* warns on forgotten escaping
This commit is contained in:
Ronny Pfannschmidt 2021-04-02 00:59:34 +02:00
parent 1ddb0696d3
commit f434783248
3 changed files with 23 additions and 17 deletions

View File

@ -672,10 +672,11 @@ class ExceptionInfo(Generic[E]):
If it matches `True` is returned, otherwise an `AssertionError` is raised. If it matches `True` is returned, otherwise an `AssertionError` is raised.
""" """
__tracebackhide__ = True __tracebackhide__ = True
msg = "Regex pattern {!r} does not match {!r}." value = str(self.value)
if regexp == str(self.value): msg = f"Regex pattern did not match.\n Regex: {regexp!r}\n Input: {value!r}"
msg += " Did you mean to `re.escape()` the regex?" if regexp == value:
assert re.search(regexp, str(self.value)), msg.format(regexp, str(self.value)) msg += "\n Did you mean to `re.escape()` the regex?"
assert re.search(regexp, value), msg
# Return True to allow for "assert excinfo.match()". # Return True to allow for "assert excinfo.match()".
return True return True

View File

@ -420,18 +420,20 @@ def test_match_raises_error(pytester: Pytester) -> None:
excinfo.match(r'[123]+') excinfo.match(r'[123]+')
""" """
) )
result = pytester.runpytest() result = pytester.runpytest("--tb=short")
assert result.ret != 0 assert result.ret != 0
exc_msg = "Regex pattern '[[]123[]]+' does not match 'division by zero'." match = [
result.stdout.fnmatch_lines([f"E * AssertionError: {exc_msg}"]) r"E .* AssertionError: Regex pattern did not match.",
r"E .* Regex: '\[123\]\+'",
r"E .* Input: 'division by zero'",
]
result.stdout.re_match_lines(match)
result.stdout.no_fnmatch_line("*__tracebackhide__ = True*") result.stdout.no_fnmatch_line("*__tracebackhide__ = True*")
result = pytester.runpytest("--fulltrace") result = pytester.runpytest("--fulltrace")
assert result.ret != 0 assert result.ret != 0
result.stdout.fnmatch_lines( result.stdout.re_match_lines([r".*__tracebackhide__ = True.*", *match])
["*__tracebackhide__ = True*", f"E * AssertionError: {exc_msg}"]
)
class TestFormattedExcinfo: class TestFormattedExcinfo:

View File

@ -191,10 +191,12 @@ class TestRaises:
int("asdf") int("asdf")
msg = "with base 16" msg = "with base 16"
expr = "Regex pattern {!r} does not match \"invalid literal for int() with base 10: 'asdf'\".".format( expr = (
msg "Regex pattern did not match.\n"
f" Regex: {msg!r}\n"
" Input: \"invalid literal for int() with base 10: 'asdf'\""
) )
with pytest.raises(AssertionError, match=re.escape(expr)): with pytest.raises(AssertionError, match="(?m)" + re.escape(expr)):
with pytest.raises(ValueError, match=msg): with pytest.raises(ValueError, match=msg):
int("asdf", base=10) int("asdf", base=10)
@ -217,7 +219,7 @@ class TestRaises:
with pytest.raises(AssertionError, match="'foo"): with pytest.raises(AssertionError, match="'foo"):
raise AssertionError("'bar") raise AssertionError("'bar")
(msg,) = excinfo.value.args (msg,) = excinfo.value.args
assert msg == 'Regex pattern "\'foo" does not match "\'bar".' assert msg == '''Regex pattern did not match.\n Regex: "'foo"\n Input: "'bar"'''
def test_match_failure_exact_string_message(self): def test_match_failure_exact_string_message(self):
message = "Oh here is a message with (42) numbers in parameters" message = "Oh here is a message with (42) numbers in parameters"
@ -226,9 +228,10 @@ class TestRaises:
raise AssertionError(message) raise AssertionError(message)
(msg,) = excinfo.value.args (msg,) = excinfo.value.args
assert msg == ( assert msg == (
"Regex pattern 'Oh here is a message with (42) numbers in " "Regex pattern did not match.\n"
"parameters' does not match 'Oh here is a message with (42) " " Regex: 'Oh here is a message with (42) numbers in parameters'\n"
"numbers in parameters'. Did you mean to `re.escape()` the regex?" " Input: 'Oh here is a message with (42) numbers in parameters'\n"
" Did you mean to `re.escape()` the regex?"
) )
def test_raises_match_wrong_type(self): def test_raises_match_wrong_type(self):