Skip to content

Commit

Permalink
[8.0.x] recwarn: let base exceptions propagate through pytest.warns
Browse files Browse the repository at this point in the history
… again

(cherry picked from commit 718cd40)
  • Loading branch information
bluetech committed Feb 16, 2024
1 parent d86d081 commit f1aa922
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 2 deletions.
1 change: 1 addition & 0 deletions changelog/11907.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +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.
12 changes: 12 additions & 0 deletions src/_pytest/recwarn.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from _pytest.deprecated import check_ispytest
from _pytest.deprecated import WARNS_NONE_ARG
from _pytest.fixtures import fixture
from _pytest.outcomes import Exit
from _pytest.outcomes import fail


Expand Down Expand Up @@ -312,6 +313,17 @@ def __exit__(
# nothing to do in this deprecated case, see WARNS_NONE_ARG above
return

# BaseExceptions like pytest.{skip,fail,xfail,exit} or Ctrl-C within
# pytest.warns should *not* trigger "DID NOT WARN" and get suppressed
# when the warning doesn't happen. Control-flow exceptions should always
# propagate.
if exc_val is not None and (
not isinstance(exc_val, Exception)
# Exit is an Exception, not a BaseException, for some reason.
or isinstance(exc_val, Exit)
):
return

def found_str():
return pformat([record.message for record in self], indent=2)

Expand Down
70 changes: 68 additions & 2 deletions testing/test_recwarn.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
from typing import Type
import warnings

from _pytest.pytester import Pytester
from _pytest.recwarn import WarningsRecorder
import pytest
from pytest import ExitCode
from pytest import Pytester
from pytest import WarningsRecorder


def test_recwarn_stacklevel(recwarn: WarningsRecorder) -> None:
Expand Down Expand Up @@ -484,3 +485,68 @@ def test_catch_warning_within_raise(self) -> None:
with pytest.raises(ValueError, match="some exception"):
warnings.warn("some warning", category=FutureWarning)
raise ValueError("some exception")

def test_skip_within_warns(self, pytester: Pytester) -> None:
"""Regression test for #11907."""
pytester.makepyfile(
"""
import pytest
def test_it():
with pytest.warns(Warning):
pytest.skip("this is OK")
""",
)

result = pytester.runpytest()
assert result.ret == ExitCode.OK
result.assert_outcomes(skipped=1)

def test_fail_within_warns(self, pytester: Pytester) -> None:
"""Regression test for #11907."""
pytester.makepyfile(
"""
import pytest
def test_it():
with pytest.warns(Warning):
pytest.fail("BOOM")
""",
)

result = pytester.runpytest()
assert result.ret == ExitCode.TESTS_FAILED
result.assert_outcomes(failed=1)
assert "DID NOT WARN" not in str(result.stdout)

def test_exit_within_warns(self, pytester: Pytester) -> None:
"""Regression test for #11907."""
pytester.makepyfile(
"""
import pytest
def test_it():
with pytest.warns(Warning):
pytest.exit("BOOM")
""",
)

result = pytester.runpytest()
assert result.ret == ExitCode.INTERRUPTED
result.assert_outcomes()

def test_keyboard_interrupt_within_warns(self, pytester: Pytester) -> None:
"""Regression test for #11907."""
pytester.makepyfile(
"""
import pytest
def test_it():
with pytest.warns(Warning):
raise KeyboardInterrupt()
""",
)

result = pytester.runpytest_subprocess()
assert result.ret == ExitCode.INTERRUPTED
result.assert_outcomes()

0 comments on commit f1aa922

Please sign in to comment.