Skip to content

Commit c7328e5

Browse files
enhance excinfo.match failure output
* now multiline and compares regexes * warns on forgotten escaping
1 parent 24d9a2f commit c7328e5

File tree

3 files changed

+23
-17
lines changed

3 files changed

+23
-17
lines changed

src/_pytest/_code/code.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -662,10 +662,11 @@ def match(self, regexp: Union[str, Pattern[str]]) -> "Literal[True]":
662662
If it matches `True` is returned, otherwise an `AssertionError` is raised.
663663
"""
664664
__tracebackhide__ = True
665-
msg = "Regex pattern {!r} does not match {!r}."
666-
if regexp == str(self.value):
667-
msg += " Did you mean to `re.escape()` the regex?"
668-
assert re.search(regexp, str(self.value)), msg.format(regexp, str(self.value))
665+
value = str(self.value)
666+
msg = f"Regex pattern did not match.\n Regex: {regexp!r}\n Input: {value!r}"
667+
if regexp == value:
668+
msg += "\n Did you mean to `re.escape()` the regex?"
669+
assert re.search(regexp, value), msg
669670
# Return True to allow for "assert excinfo.match()".
670671
return True
671672

testing/code/test_excinfo.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -420,18 +420,20 @@ def test_division_zero():
420420
excinfo.match(r'[123]+')
421421
"""
422422
)
423-
result = pytester.runpytest()
423+
result = pytester.runpytest("--tb=short")
424424
assert result.ret != 0
425425

426-
exc_msg = "Regex pattern '[[]123[]]+' does not match 'division by zero'."
427-
result.stdout.fnmatch_lines([f"E * AssertionError: {exc_msg}"])
426+
match = [
427+
r"E .* AssertionError: Regex pattern did not match.",
428+
r"E .* Regex: '\[123\]\+'",
429+
r"E .* Input: 'division by zero'",
430+
]
431+
result.stdout.re_match_lines(match)
428432
result.stdout.no_fnmatch_line("*__tracebackhide__ = True*")
429433

430434
result = pytester.runpytest("--fulltrace")
431435
assert result.ret != 0
432-
result.stdout.fnmatch_lines(
433-
["*__tracebackhide__ = True*", f"E * AssertionError: {exc_msg}"]
434-
)
436+
result.stdout.re_match_lines([r".*__tracebackhide__ = True.*", *match])
435437

436438

437439
class TestFormattedExcinfo:

testing/python/raises.py

+10-7
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,12 @@ def test_raises_match(self) -> None:
191191
int("asdf")
192192

193193
msg = "with base 16"
194-
expr = "Regex pattern {!r} does not match \"invalid literal for int() with base 10: 'asdf'\".".format(
195-
msg
194+
expr = (
195+
"Regex pattern did not match.\n"
196+
f" Regex: {msg!r}\n"
197+
" Input: \"invalid literal for int() with base 10: 'asdf'\""
196198
)
197-
with pytest.raises(AssertionError, match=re.escape(expr)):
199+
with pytest.raises(AssertionError, match="(?m)" + re.escape(expr)):
198200
with pytest.raises(ValueError, match=msg):
199201
int("asdf", base=10)
200202

@@ -217,7 +219,7 @@ def test_match_failure_string_quoting(self):
217219
with pytest.raises(AssertionError, match="'foo"):
218220
raise AssertionError("'bar")
219221
(msg,) = excinfo.value.args
220-
assert msg == 'Regex pattern "\'foo" does not match "\'bar".'
222+
assert msg == '''Regex pattern did not match.\n Regex: "'foo"\n Input: "'bar"'''
221223

222224
def test_match_failure_exact_string_message(self):
223225
message = "Oh here is a message with (42) numbers in parameters"
@@ -226,9 +228,10 @@ def test_match_failure_exact_string_message(self):
226228
raise AssertionError(message)
227229
(msg,) = excinfo.value.args
228230
assert msg == (
229-
"Regex pattern 'Oh here is a message with (42) numbers in "
230-
"parameters' does not match 'Oh here is a message with (42) "
231-
"numbers in parameters'. Did you mean to `re.escape()` the regex?"
231+
"Regex pattern did not match.\n"
232+
" Regex: 'Oh here is a message with (42) numbers in parameters'\n"
233+
" Input: 'Oh here is a message with (42) numbers in parameters'\n"
234+
" Did you mean to `re.escape()` the regex?"
232235
)
233236

234237
def test_raises_match_wrong_type(self):

0 commit comments

Comments
 (0)