diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 5452b7cb9..efe2a3dc6 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -135,8 +135,9 @@ def warns( # noqa: F811 >>> with pytest.warns(UserWarning, match=r'must be \d+$'): ... warnings.warn("value must be 42", UserWarning) - >>> with pytest.warns(UserWarning, match=r'must be \d+$'): - ... warnings.warn("this is not here", UserWarning) + >>> with pytest.warns(UserWarning): # catch re-emitted warning + ... with pytest.warns(UserWarning, match=r'must be \d+$'): + ... warnings.warn("this is not here", UserWarning) Traceback (most recent call last): ... Failed: DID NOT WARN. No warnings of type ...UserWarning... were emitted... @@ -327,7 +328,7 @@ class WarningsChecker(WarningsRecorder): if not self.matches(w): warnings.warn_explicit( str(w.message), - w.message.__class__, + w.message.__class__, # type: ignore w.filename, w.lineno, module=w.__module__, diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index a423b2001..6b3856bd9 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -203,19 +203,21 @@ class TestDeprecatedCall: def f(): warnings.warn(warning("hi")) - with pytest.raises(pytest.fail.Exception): - pytest.deprecated_call(f) - with pytest.raises(pytest.fail.Exception): - with pytest.deprecated_call(): - f() + with pytest.warns(warning): + with pytest.raises(pytest.fail.Exception): + pytest.deprecated_call(f) + with pytest.raises(pytest.fail.Exception): + with pytest.deprecated_call(): + f() def test_deprecated_call_supports_match(self) -> None: with pytest.deprecated_call(match=r"must be \d+$"): warnings.warn("value must be 42", DeprecationWarning) - with pytest.raises(pytest.fail.Exception): - with pytest.deprecated_call(match=r"must be \d+$"): - warnings.warn("this is not here", DeprecationWarning) + with pytest.deprecated_call(): + with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): + with pytest.deprecated_call(match=r"must be \d+$"): + warnings.warn("this is not here", DeprecationWarning) class TestWarns: @@ -227,8 +229,9 @@ class TestWarns: def test_several_messages(self) -> None: # different messages, b/c Python suppresses multiple identical warnings pytest.warns(RuntimeWarning, lambda: warnings.warn("w1", RuntimeWarning)) - with pytest.raises(pytest.fail.Exception): - pytest.warns(UserWarning, lambda: warnings.warn("w2", RuntimeWarning)) + with pytest.warns(RuntimeWarning): + with pytest.raises(pytest.fail.Exception): + pytest.warns(UserWarning, lambda: warnings.warn("w2", RuntimeWarning)) pytest.warns(RuntimeWarning, lambda: warnings.warn("w3", RuntimeWarning)) def test_function(self) -> None: @@ -243,13 +246,14 @@ class TestWarns: pytest.warns( (RuntimeWarning, SyntaxWarning), lambda: warnings.warn("w2", SyntaxWarning) ) - pytest.raises( - pytest.fail.Exception, - lambda: pytest.warns( - (RuntimeWarning, SyntaxWarning), - lambda: warnings.warn("w3", UserWarning), - ), - ) + with pytest.warns(): + pytest.raises( + pytest.fail.Exception, + lambda: pytest.warns( + (RuntimeWarning, SyntaxWarning), + lambda: warnings.warn("w3", UserWarning), + ), + ) def test_as_contextmanager(self) -> None: with pytest.warns(RuntimeWarning): @@ -258,20 +262,22 @@ class TestWarns: with pytest.warns(UserWarning): warnings.warn("user", UserWarning) - with pytest.raises(pytest.fail.Exception) as excinfo: - with pytest.warns(RuntimeWarning): - warnings.warn("user", UserWarning) + with pytest.warns(): + with pytest.raises(pytest.fail.Exception) as excinfo: + with pytest.warns(RuntimeWarning): + warnings.warn("user", UserWarning) excinfo.match( r"DID NOT WARN. No warnings of type \(.+RuntimeWarning.+,\) were emitted.\n" - r"The list of emitted warnings is: \[UserWarning\('user',?\)\]." + r" Emitted warnings: \[UserWarning\('user',?\)\]." ) - with pytest.raises(pytest.fail.Exception) as excinfo: - with pytest.warns(UserWarning): - warnings.warn("runtime", RuntimeWarning) + with pytest.warns(): + with pytest.raises(pytest.fail.Exception) as excinfo: + with pytest.warns(UserWarning): + warnings.warn("runtime", RuntimeWarning) excinfo.match( r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) were emitted.\n" - r"The list of emitted warnings is: \[RuntimeWarning\('runtime',?\)]." + r" Emitted warnings: \[RuntimeWarning\('runtime',?\)]." ) with pytest.raises(pytest.fail.Exception) as excinfo: @@ -279,19 +285,20 @@ class TestWarns: pass excinfo.match( r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) were emitted.\n" - r"The list of emitted warnings is: \[\]." + r" Emitted warnings: \[\]." ) warning_classes = (UserWarning, FutureWarning) - with pytest.raises(pytest.fail.Exception) as excinfo: - with pytest.warns(warning_classes) as warninfo: - warnings.warn("runtime", RuntimeWarning) - warnings.warn("import", ImportWarning) + with pytest.warns(): + with pytest.raises(pytest.fail.Exception) as excinfo: + with pytest.warns(warning_classes) as warninfo: + warnings.warn("runtime", RuntimeWarning) + warnings.warn("import", ImportWarning) messages = [each.message for each in warninfo] expected_str = ( f"DID NOT WARN. No warnings of type {warning_classes} were emitted.\n" - f"The list of emitted warnings is: {messages}." + f" Emitted warnings: {messages}." ) assert str(excinfo.value) == expected_str @@ -367,27 +374,31 @@ class TestWarns: with pytest.warns(UserWarning, match=r"must be \d+$"): warnings.warn("value must be 42", UserWarning) - with pytest.raises(pytest.fail.Exception): - with pytest.warns(UserWarning, match=r"must be \d+$"): - warnings.warn("this is not here", UserWarning) + with pytest.warns(): + with pytest.raises(pytest.fail.Exception): + with pytest.warns(UserWarning, match=r"must be \d+$"): + warnings.warn("this is not here", UserWarning) - with pytest.raises(pytest.fail.Exception): - with pytest.warns(FutureWarning, match=r"must be \d+$"): - warnings.warn("value must be 42", UserWarning) + with pytest.warns(): + with pytest.raises(pytest.fail.Exception): + with pytest.warns(FutureWarning, match=r"must be \d+$"): + warnings.warn("value must be 42", UserWarning) def test_one_from_multiple_warns(self) -> None: - with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): - with pytest.warns(UserWarning, match=r"aaa"): + with pytest.warns(): + with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): with pytest.warns(UserWarning, match=r"aaa"): - warnings.warn("cccccccccc", UserWarning) - warnings.warn("bbbbbbbbbb", UserWarning) - warnings.warn("aaaaaaaaaa", UserWarning) + with pytest.warns(UserWarning, match=r"aaa"): + warnings.warn("cccccccccc", UserWarning) + warnings.warn("bbbbbbbbbb", UserWarning) + warnings.warn("aaaaaaaaaa", UserWarning) def test_none_of_multiple_warns(self) -> None: - with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): - with pytest.warns(UserWarning, match=r"aaa"): - warnings.warn("bbbbbbbbbb", UserWarning) - warnings.warn("cccccccccc", UserWarning) + with pytest.warns(): + with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): + with pytest.warns(UserWarning, match=r"aaa"): + warnings.warn("bbbbbbbbbb", UserWarning) + warnings.warn("cccccccccc", UserWarning) @pytest.mark.filterwarnings("ignore") def test_can_capture_previously_warned(self) -> None: