Skip to content

Commit 0fe37b0

Browse files
committed
fix overriden/extended fixtures
1 parent 1443778 commit 0fe37b0

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

src/_pytest/fixtures.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,20 @@ def getfixtureclosure(
15211521
# to re-discover fixturedefs again for each fixturename
15221522
# (discovering matching fixtures for a given name/node is expensive).
15231523

1524+
def dependent_fixtures_argnames(
1525+
fixture_defs: Sequence[FixtureDef[Any]],
1526+
) -> List[str]:
1527+
last_fixture = fixture_defs[-1]
1528+
# Initialize with the argnames of the last fixture
1529+
dependent_argnames = list(last_fixture.argnames)
1530+
for arg in fixture_defs:
1531+
if arg.argname in last_fixture.argnames:
1532+
# Add new argument names maintaining order and avoiding duplicates
1533+
for argname in arg.argnames:
1534+
if argname not in dependent_argnames:
1535+
dependent_argnames.append(argname)
1536+
return dependent_argnames
1537+
15241538
fixturenames_closure = list(initialnames)
15251539

15261540
arg2fixturedefs: Dict[str, Sequence[FixtureDef[Any]]] = {}
@@ -1535,7 +1549,8 @@ def getfixtureclosure(
15351549
fixturedefs = self.getfixturedefs(argname, parentnode)
15361550
if fixturedefs:
15371551
arg2fixturedefs[argname] = fixturedefs
1538-
for arg in fixturedefs[-1].argnames:
1552+
argnames = dependent_fixtures_argnames(fixturedefs)
1553+
for arg in argnames:
15391554
if arg not in fixturenames_closure:
15401555
fixturenames_closure.append(arg)
15411556

testing/test_mark.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,35 @@ def test_func(a, b):
447447
assert result.ret == 0
448448

449449

450+
def test_parametrize_overriden_extended_fixture(pytester: Pytester) -> None:
451+
"""Overriden fixtures must pass over dependend fixtures for parameterization (#12091)"""
452+
py_file = pytester.makepyfile(
453+
"""\
454+
import pytest
455+
456+
@pytest.fixture
457+
def param() -> int:
458+
return 1
459+
460+
@pytest.fixture
461+
def main(param: int) -> int:
462+
return sum(range(param + 1))
463+
464+
465+
class TestFoo:
466+
@pytest.fixture
467+
def main(self, main: int) -> int:
468+
return main
469+
470+
@pytest.mark.parametrize("param", [2])
471+
def test_foo(self, main: int) -> None:
472+
assert main == 3
473+
"""
474+
)
475+
result = pytester.runpytest(py_file)
476+
assert result.ret == 0
477+
478+
450479
def test_parametrize_iterator(pytester: Pytester) -> None:
451480
"""`parametrize` should work with generators (#5354)."""
452481
py_file = pytester.makepyfile(

0 commit comments

Comments
 (0)