Skip to content

Commit 92203d2

Browse files
authored
Merge pull request #11990 from bluetech/backport-11920
[8.0.x] recwarn: let base exceptions propagate through `pytest.warns` again
2 parents d86d081 + f1aa922 commit 92203d2

File tree

3 files changed

+81
-2
lines changed

3 files changed

+81
-2
lines changed

changelog/11907.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a regression in pytest 8.0.0 whereby calling :func:`pytest.skip` and similar control-flow exceptions within a :func:`pytest.warns()` block would get suppressed instead of propagating.

src/_pytest/recwarn.py

+12
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from _pytest.deprecated import check_ispytest
2222
from _pytest.deprecated import WARNS_NONE_ARG
2323
from _pytest.fixtures import fixture
24+
from _pytest.outcomes import Exit
2425
from _pytest.outcomes import fail
2526

2627

@@ -312,6 +313,17 @@ def __exit__(
312313
# nothing to do in this deprecated case, see WARNS_NONE_ARG above
313314
return
314315

316+
# BaseExceptions like pytest.{skip,fail,xfail,exit} or Ctrl-C within
317+
# pytest.warns should *not* trigger "DID NOT WARN" and get suppressed
318+
# when the warning doesn't happen. Control-flow exceptions should always
319+
# propagate.
320+
if exc_val is not None and (
321+
not isinstance(exc_val, Exception)
322+
# Exit is an Exception, not a BaseException, for some reason.
323+
or isinstance(exc_val, Exit)
324+
):
325+
return
326+
315327
def found_str():
316328
return pformat([record.message for record in self], indent=2)
317329

testing/test_recwarn.py

+68-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
from typing import Type
44
import warnings
55

6-
from _pytest.pytester import Pytester
7-
from _pytest.recwarn import WarningsRecorder
86
import pytest
7+
from pytest import ExitCode
8+
from pytest import Pytester
9+
from pytest import WarningsRecorder
910

1011

1112
def test_recwarn_stacklevel(recwarn: WarningsRecorder) -> None:
@@ -484,3 +485,68 @@ def test_catch_warning_within_raise(self) -> None:
484485
with pytest.raises(ValueError, match="some exception"):
485486
warnings.warn("some warning", category=FutureWarning)
486487
raise ValueError("some exception")
488+
489+
def test_skip_within_warns(self, pytester: Pytester) -> None:
490+
"""Regression test for #11907."""
491+
pytester.makepyfile(
492+
"""
493+
import pytest
494+
495+
def test_it():
496+
with pytest.warns(Warning):
497+
pytest.skip("this is OK")
498+
""",
499+
)
500+
501+
result = pytester.runpytest()
502+
assert result.ret == ExitCode.OK
503+
result.assert_outcomes(skipped=1)
504+
505+
def test_fail_within_warns(self, pytester: Pytester) -> None:
506+
"""Regression test for #11907."""
507+
pytester.makepyfile(
508+
"""
509+
import pytest
510+
511+
def test_it():
512+
with pytest.warns(Warning):
513+
pytest.fail("BOOM")
514+
""",
515+
)
516+
517+
result = pytester.runpytest()
518+
assert result.ret == ExitCode.TESTS_FAILED
519+
result.assert_outcomes(failed=1)
520+
assert "DID NOT WARN" not in str(result.stdout)
521+
522+
def test_exit_within_warns(self, pytester: Pytester) -> None:
523+
"""Regression test for #11907."""
524+
pytester.makepyfile(
525+
"""
526+
import pytest
527+
528+
def test_it():
529+
with pytest.warns(Warning):
530+
pytest.exit("BOOM")
531+
""",
532+
)
533+
534+
result = pytester.runpytest()
535+
assert result.ret == ExitCode.INTERRUPTED
536+
result.assert_outcomes()
537+
538+
def test_keyboard_interrupt_within_warns(self, pytester: Pytester) -> None:
539+
"""Regression test for #11907."""
540+
pytester.makepyfile(
541+
"""
542+
import pytest
543+
544+
def test_it():
545+
with pytest.warns(Warning):
546+
raise KeyboardInterrupt()
547+
""",
548+
)
549+
550+
result = pytester.runpytest_subprocess()
551+
assert result.ret == ExitCode.INTERRUPTED
552+
result.assert_outcomes()

0 commit comments

Comments
 (0)