Emit unmatched warnings from pytest.warns()
This commit is contained in:
parent
a50ea1b8e7
commit
9279ea2882
1
AUTHORS
1
AUTHORS
|
@ -311,6 +311,7 @@ Raphael Pierzina
|
|||
Rafal Semik
|
||||
Raquel Alegre
|
||||
Ravi Chandra
|
||||
Reagan Lee
|
||||
Robert Holt
|
||||
Roberto Aldera
|
||||
Roberto Polli
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Set :func:`warns` to re-emit unmatched warnings when the context closes
|
|
@ -149,6 +149,10 @@ def warns( # noqa: F811
|
|||
This could be achieved in the same way as with exceptions, see
|
||||
:ref:`parametrizing_conditional_raising` for an example.
|
||||
|
||||
.. note::
|
||||
Unlike the stdlib :func:`warnings.catch_warnings` context manager,
|
||||
unmatched warnings will be re-emitted when the context closes.
|
||||
|
||||
"""
|
||||
__tracebackhide__ = True
|
||||
if not args:
|
||||
|
@ -290,6 +294,32 @@ class WarningsChecker(WarningsRecorder):
|
|||
def found_str():
|
||||
return pformat([record.message for record in self], indent=2)
|
||||
|
||||
def re_emit() -> None:
|
||||
for r in self:
|
||||
if matches(r):
|
||||
continue
|
||||
|
||||
assert issubclass(r.message.__class__, Warning)
|
||||
|
||||
warnings.warn_explicit(
|
||||
str(r.message),
|
||||
r.message.__class__,
|
||||
r.filename,
|
||||
r.lineno,
|
||||
module=r.__module__,
|
||||
source=r.source,
|
||||
)
|
||||
|
||||
def matches(warning) -> bool:
|
||||
if self.expected_warning is not None:
|
||||
if issubclass(warning.category, self.expected_warning):
|
||||
if self.match_expr is not None:
|
||||
if re.compile(self.match_expr).search(str(warning.message)):
|
||||
return True
|
||||
return False
|
||||
return True
|
||||
return False
|
||||
|
||||
# only check if we're not currently handling an exception
|
||||
if exc_type is None and exc_val is None and exc_tb is None:
|
||||
if self.expected_warning is not None:
|
||||
|
@ -303,6 +333,7 @@ class WarningsChecker(WarningsRecorder):
|
|||
for r in self:
|
||||
if issubclass(r.category, self.expected_warning):
|
||||
if re.compile(self.match_expr).search(str(r.message)):
|
||||
re_emit()
|
||||
break
|
||||
else:
|
||||
fail(
|
||||
|
@ -311,3 +342,5 @@ DID NOT WARN. No warnings of type {self.expected_warning} matching the regex wer
|
|||
Regex: {self.match_expr}
|
||||
Emitted warnings: {found_str()}"""
|
||||
)
|
||||
else:
|
||||
re_emit()
|
||||
|
|
|
@ -376,10 +376,12 @@ class TestWarns:
|
|||
warnings.warn("value must be 42", UserWarning)
|
||||
|
||||
def test_one_from_multiple_warns(self) -> None:
|
||||
with pytest.warns(UserWarning, match=r"aaa"):
|
||||
warnings.warn("cccccccccc", UserWarning)
|
||||
warnings.warn("bbbbbbbbbb", UserWarning)
|
||||
warnings.warn("aaaaaaaaaa", UserWarning)
|
||||
with pytest.raises(pytest.fail.Exception):
|
||||
with pytest.warns(UserWarning, match=r"aaa"):
|
||||
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):
|
||||
|
@ -403,3 +405,33 @@ class TestWarns:
|
|||
with pytest.warns(UserWarning, foo="bar"): # type: ignore
|
||||
pass
|
||||
assert "Unexpected keyword arguments" in str(excinfo.value)
|
||||
|
||||
def test_re_emit_single(self) -> None:
|
||||
with pytest.warns(DeprecationWarning):
|
||||
with pytest.warns(UserWarning):
|
||||
warnings.warn("user warning", UserWarning)
|
||||
warnings.warn("some deprecation warning", DeprecationWarning)
|
||||
|
||||
def test_re_emit_multiple(self) -> None:
|
||||
with pytest.warns(UserWarning):
|
||||
warnings.warn("first warning", UserWarning)
|
||||
warnings.warn("second warning", UserWarning)
|
||||
|
||||
def test_re_emit_match_single(self) -> None:
|
||||
with pytest.warns(DeprecationWarning):
|
||||
with pytest.warns(UserWarning, match="user warning"):
|
||||
warnings.warn("user warning", UserWarning)
|
||||
warnings.warn("some deprecation warning", DeprecationWarning)
|
||||
|
||||
def test_re_emit_match_multiple(self) -> None:
|
||||
# with pytest.warns(UserWarning):
|
||||
with pytest.warns(UserWarning, match="user warning"):
|
||||
warnings.warn("first user warning", UserWarning)
|
||||
warnings.warn("second user warning", UserWarning)
|
||||
|
||||
def test_re_emit_non_match_single(self) -> None:
|
||||
# with pytest.warns(UserWarning):
|
||||
with pytest.warns(UserWarning, match="v2 warning"):
|
||||
with pytest.warns(UserWarning, match="v1 warning"):
|
||||
warnings.warn("v1 warning", UserWarning)
|
||||
warnings.warn("non-matching v2 warning", UserWarning)
|
||||
|
|
Loading…
Reference in New Issue