Skip to content

Commit 0b91d5e

Browse files
committed
fixtures: fix tracebacks for higher-scoped failed fixtures getting longer and longer
Fix pytest-dev#12204.
1 parent 127a372 commit 0b91d5e

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

changelog/12204.bugfix.rst

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix a regression in pytest 8.0 where tracebacks get longer and longer when multiple tests fail due to a shared higher-scope fixture which raised.
2+
3+
The fix necessitated internal changes which may affect some plugins:
4+
- ``FixtureDef.cached_result[2]`` is now a tuple ``(exc, tb)`` instead of ``exc``.

src/_pytest/fixtures.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import os
99
from pathlib import Path
1010
import sys
11+
import types
1112
from typing import AbstractSet
1213
from typing import Any
1314
from typing import Callable
@@ -104,8 +105,8 @@
104105
None,
105106
# Cache key.
106107
object,
107-
# Exception if raised.
108-
BaseException,
108+
# The exception and the original traceback.
109+
Tuple[BaseException, Optional[types.TracebackType]],
109110
],
110111
]
111112

@@ -1049,8 +1050,8 @@ def execute(self, request: SubRequest) -> FixtureValue:
10491050
# numpy arrays (#6497).
10501051
if my_cache_key is cache_key:
10511052
if self.cached_result[2] is not None:
1052-
exc = self.cached_result[2]
1053-
raise exc
1053+
exc, exc_tb = self.cached_result[2]
1054+
raise exc.with_traceback(exc_tb)
10541055
else:
10551056
result = self.cached_result[0]
10561057
return result
@@ -1126,7 +1127,7 @@ def pytest_fixture_setup(
11261127
# Don't show the fixture as the skip location, as then the user
11271128
# wouldn't know which test skipped.
11281129
e._use_item_location = True
1129-
fixturedef.cached_result = (None, my_cache_key, e)
1130+
fixturedef.cached_result = (None, my_cache_key, (e, e.__traceback__))
11301131
raise
11311132
fixturedef.cached_result = (result, my_cache_key, None)
11321133
return result

testing/python/fixtures.py

+22
Original file line numberDiff line numberDiff line change
@@ -3397,6 +3397,28 @@ def test_something():
33973397
["*def gen(qwe123):*", "*fixture*qwe123*not found*", "*1 error*"]
33983398
)
33993399

3400+
def test_cached_exception_doesnt_get_longer(self, pytester: Pytester) -> None:
3401+
"""Regression test for #12204."""
3402+
pytester.makepyfile(
3403+
"""
3404+
import pytest
3405+
@pytest.fixture(scope="session")
3406+
def bad(): 1 / 0
3407+
3408+
def test_1(bad): pass
3409+
def test_2(bad): pass
3410+
def test_3(bad): pass
3411+
"""
3412+
)
3413+
3414+
result = pytester.runpytest_inprocess("--tb=native")
3415+
assert result.ret == ExitCode.TESTS_FAILED
3416+
failures = result.reprec.getfailures() # type: ignore[attr-defined]
3417+
assert len(failures) == 3
3418+
lines1 = failures[1].longrepr.reprtraceback.reprentries[0].lines
3419+
lines2 = failures[2].longrepr.reprtraceback.reprentries[0].lines
3420+
assert len(lines1) == len(lines2)
3421+
34003422

34013423
class TestShowFixtures:
34023424
def test_funcarg_compat(self, pytester: Pytester) -> None:

0 commit comments

Comments
 (0)