Skip to content

Commit 143c703

Browse files
committed
fix overriden/extended fixtures
1 parent 2607fe8 commit 143c703

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
@@ -1505,6 +1505,20 @@ def getfixtureclosure(
15051505
# to re-discover fixturedefs again for each fixturename
15061506
# (discovering matching fixtures for a given name/node is expensive).
15071507

1508+
def dependent_fixtures_argnames(
1509+
fixture_defs: Sequence[FixtureDef[Any]],
1510+
) -> List[str]:
1511+
last_fixture = fixture_defs[-1]
1512+
# Initialize with the argnames of the last fixture
1513+
dependent_argnames = list(last_fixture.argnames)
1514+
for arg in fixture_defs:
1515+
if arg.argname in last_fixture.argnames:
1516+
# Add new argument names maintaining order and avoiding duplicates
1517+
for argname in arg.argnames:
1518+
if argname not in dependent_argnames:
1519+
dependent_argnames.append(argname)
1520+
return dependent_argnames
1521+
15081522
fixturenames_closure = list(initialnames)
15091523

15101524
arg2fixturedefs: Dict[str, Sequence[FixtureDef[Any]]] = {}
@@ -1519,7 +1533,8 @@ def getfixtureclosure(
15191533
fixturedefs = self.getfixturedefs(argname, parentnode)
15201534
if fixturedefs:
15211535
arg2fixturedefs[argname] = fixturedefs
1522-
for arg in fixturedefs[-1].argnames:
1536+
argnames = dependent_fixtures_argnames(fixturedefs)
1537+
for arg in argnames:
15231538
if arg not in fixturenames_closure:
15241539
fixturenames_closure.append(arg)
15251540

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)