File tree Expand file tree Collapse file tree 4 files changed +52
-3
lines changed Expand file tree Collapse file tree 4 files changed +52
-3
lines changed Original file line number Diff line number Diff line change @@ -342,6 +342,7 @@ Olga Matoula
342342Oliver Bestwalter
343343Omar Kohl
344344Omer Hadari
345+ Omri Golan
345346Ondřej Súkup
346347Oscar Benjamin
347348Parth Patel
Original file line number Diff line number Diff line change 1+ Fixed an issue where internal exceptions like those raised from :func: `pytest.exit ` would not be correctly handled during test teardown.
Original file line number Diff line number Diff line change @@ -342,10 +342,26 @@ def from_call(
342342 instant = timing .Instant ()
343343 try :
344344 result : TResult | None = func ()
345- except BaseException :
345+ except BaseException as caught :
346346 excinfo = ExceptionInfo .from_current ()
347- if reraise is not None and isinstance (excinfo .value , reraise ):
348- raise
347+ val = excinfo .value
348+
349+ if reraise is not None :
350+ reraise_types = (
351+ (reraise ,) if not isinstance (reraise , tuple ) else reraise
352+ )
353+
354+ # ExceptionGroup-aware path: check if any of the direct children
355+ # is an instance of the `reraise` parameter, and reraise the exception
356+ # accordingly (#13650).
357+ if isinstance (val , BaseExceptionGroup ):
358+ for child in val .exceptions :
359+ if isinstance (child , reraise_types ):
360+ raise child from caught
361+ # Not an exception group, check if we need to reraise it.
362+ elif isinstance (val , reraise_types ):
363+ raise
364+
349365 result = None
350366 duration = instant .elapsed ()
351367 return cls (
Original file line number Diff line number Diff line change @@ -1264,3 +1264,34 @@ def test_bar(): pass
12641264 )
12651265 result = pytester .runpytest ("--stepwise" )
12661266 result .assert_outcomes (failed = 1 , errors = 1 )
1267+
1268+
1269+ def test_exit_in_teardown_exception_group_stops_session (pytester : Pytester ) -> None :
1270+ pytester .makepyfile (
1271+ test_it = """
1272+ import pytest
1273+ @pytest.fixture
1274+ def failing_teardown():
1275+ yield
1276+ raise IOError("Exception in teardown")
1277+ @pytest.fixture
1278+ def exit_session():
1279+ yield
1280+ pytest.exit("Forced exit")
1281+ def test_1(): return
1282+ @pytest.mark.usefixtures(
1283+ "failing_teardown",
1284+ "exit_session"
1285+ )
1286+ def test_failure(): return
1287+ def test_3(): return
1288+ """
1289+ )
1290+ result = pytester .runpytest ()
1291+ result .assert_outcomes (passed = 2 )
1292+ result .stdout .fnmatch_lines (
1293+ [
1294+ "!* _pytest.outcomes.Exit: Forced exit !*" ,
1295+ "=* 2 passed in * =*" ,
1296+ ]
1297+ )
You can’t perform that action at this time.
0 commit comments