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
342
342
Oliver Bestwalter
343
343
Omar Kohl
344
344
Omer Hadari
345
+ Omri Golan
345
346
Ondřej Súkup
346
347
Oscar Benjamin
347
348
Parth 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(
342
342
instant = timing .Instant ()
343
343
try :
344
344
result : TResult | None = func ()
345
- except BaseException :
345
+ except BaseException as caught :
346
346
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
+
349
365
result = None
350
366
duration = instant .elapsed ()
351
367
return cls (
Original file line number Diff line number Diff line change @@ -1264,3 +1264,34 @@ def test_bar(): pass
1264
1264
)
1265
1265
result = pytester .runpytest ("--stepwise" )
1266
1266
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