Skip to content

Commit bc57e69

Browse files
authored
recwarn: improved warns(match=...) error message on regex mismatch (closes pytest-dev#11225) (pytest-dev#14310)
When using pytest.warns(match=...), even if a warning of the expected type was emitted, the first sentence of the error message said "DID NOT WARN" when the regex did not match. Since this made it seem as though no warning had been emitted at all, I updated it to make the situation clearer. Closes pytest-dev#11225
1 parent 75609e7 commit bc57e69

File tree

5 files changed

+53
-9
lines changed

5 files changed

+53
-9
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ Israël Hallé
209209
Itxaso Aizpurua
210210
Iwan Briquemont
211211
Jaap Broekhuizen
212+
JaeHyuck Sa
212213
Jake VanderPlas
213214
Jakob van Santen
214215
Jakub Mitoraj

changelog/11225.improvement.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:func:`pytest.warns` now shows "Regex pattern did not match" instead of "DID NOT WARN" when warnings were emitted but the ``match`` pattern did not match.

doc/en/how-to/capture-warnings.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,9 @@ Some examples:
363363
...
364364
Traceback (most recent call last):
365365
...
366-
Failed: DID NOT WARN. No warnings of type ...UserWarning... were emitted...
366+
Failed: Regex pattern did not match any of the 1 warnings emitted.
367+
Regex: ...
368+
Emitted warnings: ...UserWarning...
367369
368370
>>> with warns(UserWarning, match=re.escape("issue with foo() func")):
369371
... warnings.warn("issue with foo() func")

src/_pytest/recwarn.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,9 @@ def warns(
139139
... warnings.warn("this is not here", UserWarning)
140140
Traceback (most recent call last):
141141
...
142-
Failed: DID NOT WARN. No warnings of type ...UserWarning... were emitted...
142+
Failed: Regex pattern did not match any of the 1 warnings emitted.
143+
Regex: ...
144+
Emitted warnings: ...UserWarning...
143145
144146
**Using with** ``pytest.mark.parametrize``
145147
@@ -321,10 +323,17 @@ def found_str() -> str:
321323
f" Emitted warnings: {found_str()}."
322324
)
323325
elif not any(self.matches(w) for w in self):
326+
escape_hint = ""
327+
if isinstance(self.match_expr, str) and any(
328+
self.match_expr == str(w.message)
329+
for w in self
330+
if issubclass(w.category, self.expected_warning)
331+
):
332+
escape_hint = "\n Did you mean to `re.escape()` the regex?"
324333
fail(
325-
f"DID NOT WARN. No warnings of type {self.expected_warning} matching the regex were emitted.\n"
326-
f" Regex: {self.match_expr}\n"
327-
f" Emitted warnings: {found_str()}."
334+
f"Regex pattern did not match any of the {len(self)} warnings emitted.\n"
335+
f" Regex: {self.match_expr!r}\n"
336+
f" Emitted warnings: {found_str()}.{escape_hint}"
328337
)
329338
finally:
330339
# Whether or not any warnings matched, we want to re-emit all unmatched warnings.

testing/test_recwarn.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,9 @@ def test_deprecated_call_supports_match(self) -> None:
243243
warnings.warn("value must be 42", DeprecationWarning)
244244

245245
with pytest.deprecated_call():
246-
with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"):
246+
with pytest.raises(
247+
pytest.fail.Exception, match="Regex pattern did not match"
248+
):
247249
with pytest.deprecated_call(match=r"must be \d+$"):
248250
warnings.warn("this is not here", DeprecationWarning)
249251

@@ -406,7 +408,9 @@ def test_match_regex(self) -> None:
406408

407409
def test_one_from_multiple_warns(self) -> None:
408410
with pytest.warns():
409-
with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"):
411+
with pytest.raises(
412+
pytest.fail.Exception, match="Regex pattern did not match"
413+
):
410414
with pytest.warns(UserWarning, match=r"aaa"):
411415
with pytest.warns(UserWarning, match=r"aaa"):
412416
warnings.warn("cccccccccc", UserWarning)
@@ -415,11 +419,38 @@ def test_one_from_multiple_warns(self) -> None:
415419

416420
def test_none_of_multiple_warns(self) -> None:
417421
with pytest.warns():
418-
with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"):
422+
with pytest.raises(
423+
pytest.fail.Exception, match="Regex pattern did not match"
424+
):
419425
with pytest.warns(UserWarning, match=r"aaa"):
420426
warnings.warn("bbbbbbbbbb", UserWarning)
421427
warnings.warn("cccccccccc", UserWarning)
422428

429+
def test_warns_match_failure_message_detail(self) -> None:
430+
with pytest.warns():
431+
with pytest.raises(pytest.fail.Exception) as excinfo:
432+
with pytest.warns(UserWarning, match=r"must be \d+$"):
433+
warnings.warn("this is not here", UserWarning)
434+
msg = str(excinfo.value)
435+
assert "Regex pattern did not match" in msg
436+
assert "this is not here" in msg
437+
assert "DID NOT WARN" not in msg
438+
439+
def test_warns_match_re_escape_hint(self) -> None:
440+
with pytest.warns():
441+
with pytest.raises(pytest.fail.Exception) as excinfo:
442+
with pytest.warns(UserWarning, match="foo (bar)"):
443+
warnings.warn("foo (bar)", UserWarning)
444+
assert "re.escape()" in str(excinfo.value)
445+
446+
def test_warns_match_re_escape_hint_no_false_positive(self) -> None:
447+
with pytest.warns():
448+
with pytest.raises(pytest.fail.Exception) as excinfo:
449+
with pytest.warns(DeprecationWarning, match="foo (bar)"):
450+
warnings.warn("some deprecation msg", DeprecationWarning)
451+
warnings.warn("foo (bar)", UserWarning)
452+
assert "re.escape()" not in str(excinfo.value)
453+
423454
@pytest.mark.filterwarnings("ignore")
424455
def test_can_capture_previously_warned(self) -> None:
425456
def f() -> int:
@@ -589,7 +620,7 @@ def __init__(self, a, b):
589620
pass
590621

591622
with pytest.warns(CustomWarning):
592-
with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"):
623+
with pytest.raises(pytest.fail.Exception, match="Regex pattern did not match"):
593624
with pytest.warns(CustomWarning, match="not gonna match"):
594625
a, b = 1, 2
595626
warnings.warn(CustomWarning(a, b))

0 commit comments

Comments
 (0)