This commit is contained in:
Andrés Sandoval 2024-07-02 20:24:20 -04:00 committed by GitHub
commit ddc41c4131
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 110 additions and 1 deletions

View File

@ -1541,6 +1541,23 @@ class FixtureManager:
# to re-discover fixturedefs again for each fixturename # to re-discover fixturedefs again for each fixturename
# (discovering matching fixtures for a given name/node is expensive). # (discovering matching fixtures for a given name/node is expensive).
def dependent_fixtures_argnames(
fixture_defs: Sequence[FixtureDef[Any]],
) -> List[str]:
# Initialize with the argnames of the last fixture
dependent_argnames = list(fixture_defs[-1].argnames)
# Iterate over the list in reverse order, skipping the last element already processed.
for index, current_fixture in enumerate(
reversed(fixture_defs[:-1]), start=1
):
if current_fixture.argname in fixture_defs[-index].argnames:
for argname in current_fixture.argnames:
if argname not in dependent_argnames:
dependent_argnames.append(argname)
else:
break
return dependent_argnames
fixturenames_closure = list(initialnames) fixturenames_closure = list(initialnames)
arg2fixturedefs: dict[str, Sequence[FixtureDef[Any]]] = {} arg2fixturedefs: dict[str, Sequence[FixtureDef[Any]]] = {}
@ -1555,7 +1572,8 @@ class FixtureManager:
fixturedefs = self.getfixturedefs(argname, parentnode) fixturedefs = self.getfixturedefs(argname, parentnode)
if fixturedefs: if fixturedefs:
arg2fixturedefs[argname] = fixturedefs arg2fixturedefs[argname] = fixturedefs
for arg in fixturedefs[-1].argnames: argnames = dependent_fixtures_argnames(fixturedefs)
for arg in argnames:
if arg not in fixturenames_closure: if arg not in fixturenames_closure:
fixturenames_closure.append(arg) fixturenames_closure.append(arg)

View File

@ -1787,6 +1787,53 @@ class TestFixtureManagerParseFactories:
result = pytester.runpytest("foo") result = pytester.runpytest("foo")
result.stdout.fnmatch_lines(["*passed*"]) result.stdout.fnmatch_lines(["*passed*"])
def test_get_fixture_clousure_override_conftest_module_and_class(
self, pytester: Pytester
):
pytester.makepyfile(
"""\
import pytest
@pytest.fixture
def hello(param, hello):
return "module"
class TestClass(object):
@pytest.fixture
def hello(self, hello):
return "class"
@pytest.mark.parametrize("param", ["foo"])
def test_hello(self, item, hello, fm):
print(item)
clousurelist, _ = fm.getfixtureclosure(item, ("hello",), {})
assert clousurelist == ["hello", "param", "request"]
"""
)
reprec = pytester.inline_run("-s")
reprec.assertoutcome(passed=1)
def test_get_fixture_clousure_override_module_and_class(self, pytester: Pytester):
pytester.makepyfile(
"""\
import pytest
@pytest.fixture
def hello(param):
return "module"
class TestClass(object):
@pytest.fixture
def hello(self, hello):
return "class"
@pytest.mark.parametrize("param", ["foo"])
def test_hello(self, item, hello, fm):
print(item)
clousurelist, _ = fm.getfixtureclosure(item, ("hello",), {})
print(clousurelist)
assert clousurelist == ["hello", "param"]
"""
)
reprec = pytester.inline_run("-s")
reprec.assertoutcome(passed=1)
class TestAutouseDiscovery: class TestAutouseDiscovery:
@pytest.fixture @pytest.fixture

View File

@ -499,6 +499,50 @@ def test_parametrized_with_kwargs(pytester: Pytester) -> None:
assert result.ret == 0 assert result.ret == 0
def test_parametrize_overriden_extended_fixture(pytester: Pytester) -> None:
"""Overriden fixtures must pass over dependend fixtures for parameterization (#12091)"""
pytester.makeconftest(
"""
import pytest
@pytest.fixture
def not_needed():
assert False, "Should not be called!"
@pytest.fixture
def main(foo):
assert False, "Should not be called!"
"""
)
py_file = pytester.makepyfile(
"""\
import pytest
@pytest.fixture
def param() -> int:
return 1
@pytest.fixture
def main(param: int) -> int:
return sum(range(param + 1))
class TestFoo:
@pytest.fixture
def main(self, main: int) -> int:
return main
@pytest.mark.parametrize("param", [2])
def test_foo(self, main: int) -> None:
assert main == 3
"""
)
result = pytester.runpytest(py_file)
assert result.ret == 0
def test_parametrize_iterator(pytester: Pytester) -> None: def test_parametrize_iterator(pytester: Pytester) -> None:
"""`parametrize` should work with generators (#5354).""" """`parametrize` should work with generators (#5354)."""
py_file = pytester.makepyfile( py_file = pytester.makepyfile(