Skip to content

Commit 718cd40

Browse files
authored
Merge pull request #11920 from bluetech/warn-skip
recwarn: let base exceptions propagate through `pytest.warns` again
2 parents 5d7a5a9 + 288201b commit 718cd40

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
@@ -20,6 +20,7 @@
2020

2121
from _pytest.deprecated import check_ispytest
2222
from _pytest.fixtures import fixture
23+
from _pytest.outcomes import Exit
2324
from _pytest.outcomes import fail
2425

2526

@@ -302,6 +303,17 @@ def __exit__(
302303

303304
__tracebackhide__ = True
304305

306+
# BaseExceptions like pytest.{skip,fail,xfail,exit} or Ctrl-C within
307+
# pytest.warns should *not* trigger "DID NOT WARN" and get suppressed
308+
# when the warning doesn't happen. Control-flow exceptions should always
309+
# propagate.
310+
if exc_val is not None and (
311+
not isinstance(exc_val, Exception)
312+
# Exit is an Exception, not a BaseException, for some reason.
313+
or isinstance(exc_val, Exit)
314+
):
315+
return
316+
305317
def found_str():
306318
return pformat([record.message for record in self], indent=2)
307319

testing/test_recwarn.py

+68-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
from typing import Type
66
import warnings
77

8-
from _pytest.pytester import Pytester
9-
from _pytest.recwarn import WarningsRecorder
108
import pytest
9+
from pytest import ExitCode
10+
from pytest import Pytester
11+
from pytest import WarningsRecorder
1112

1213

1314
def test_recwarn_stacklevel(recwarn: WarningsRecorder) -> None:
@@ -479,6 +480,71 @@ def test_catch_warning_within_raise(self) -> None:
479480
warnings.warn("some warning", category=FutureWarning)
480481
raise ValueError("some exception")
481482

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

483549
def test_raise_type_error_on_non_string_warning() -> None:
484550
"""Check pytest.warns validates warning messages are strings (#10865)."""

0 commit comments

Comments
 (0)