Fix a bug
This commit is contained in:
parent
bbf594903e
commit
80b4f8be1c
|
@ -1414,11 +1414,10 @@ class FixtureManager:
|
||||||
tuple(self._getautousenames(node.nodeid)) + usefixtures + argnames
|
tuple(self._getautousenames(node.nodeid)) + usefixtures + argnames
|
||||||
)
|
)
|
||||||
|
|
||||||
arg2fixturedefs: Dict[str, Sequence[FixtureDef[Any]]] = {}
|
names_closure, arg2fixturedefs = self.getfixtureclosure(
|
||||||
names_closure = self.getfixtureclosure(
|
|
||||||
node,
|
node,
|
||||||
initialnames,
|
initialnames,
|
||||||
arg2fixturedefs,
|
None,
|
||||||
ignore_args=_get_direct_parametrize_args(node),
|
ignore_args=_get_direct_parametrize_args(node),
|
||||||
)
|
)
|
||||||
return FuncFixtureInfo(
|
return FuncFixtureInfo(
|
||||||
|
@ -1461,9 +1460,9 @@ class FixtureManager:
|
||||||
self,
|
self,
|
||||||
parentnode: nodes.Node,
|
parentnode: nodes.Node,
|
||||||
initialnames: Tuple[str, ...],
|
initialnames: Tuple[str, ...],
|
||||||
arg2fixturedefs: Dict[str, Sequence[FixtureDef[Any]]],
|
arg2fixturedefs: Union[Dict[str, Sequence[FixtureDef[Any]]], None],
|
||||||
ignore_args: Sequence[str] = (),
|
ignore_args: Sequence[str] = (),
|
||||||
) -> List[str]:
|
) -> Tuple[List[str], Dict[str, Sequence[FixtureDef[Any]]]]:
|
||||||
# Collect the closure of all fixtures, starting with the given
|
# Collect the closure of all fixtures, starting with the given
|
||||||
# initialnames containing function arguments, `usefixture` markers
|
# initialnames containing function arguments, `usefixture` markers
|
||||||
# and `autouse` fixtures as the initial set. As we have to visit all
|
# and `autouse` fixtures as the initial set. As we have to visit all
|
||||||
|
@ -1474,6 +1473,8 @@ class FixtureManager:
|
||||||
|
|
||||||
fixturenames_closure = initialnames
|
fixturenames_closure = initialnames
|
||||||
|
|
||||||
|
if arg2fixturedefs is None:
|
||||||
|
arg2fixturedefs = {}
|
||||||
lastlen = -1
|
lastlen = -1
|
||||||
parentid = parentnode.nodeid
|
parentid = parentnode.nodeid
|
||||||
while lastlen != len(fixturenames_closure):
|
while lastlen != len(fixturenames_closure):
|
||||||
|
@ -1498,7 +1499,10 @@ class FixtureManager:
|
||||||
else:
|
else:
|
||||||
return fixturedefs[-1]._scope
|
return fixturedefs[-1]._scope
|
||||||
|
|
||||||
return sorted(fixturenames_closure, key=sort_by_scope, reverse=True)
|
return (
|
||||||
|
sorted(fixturenames_closure, key=sort_by_scope, reverse=True),
|
||||||
|
arg2fixturedefs,
|
||||||
|
)
|
||||||
|
|
||||||
def pytest_generate_tests(self, metafunc: "Metafunc") -> None:
|
def pytest_generate_tests(self, metafunc: "Metafunc") -> None:
|
||||||
"""Generate new tests based on parametrized fixtures used by the given metafunc"""
|
"""Generate new tests based on parametrized fixtures used by the given metafunc"""
|
||||||
|
|
|
@ -381,21 +381,9 @@ del _EmptyClass
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
|
|
||||||
def prune_dependency_tree_if_test_is_dynamically_parametrized(metafunc):
|
def check_if_test_is_dynamically_parametrized(metafunc):
|
||||||
if metafunc._calls:
|
if metafunc._calls:
|
||||||
# Dynamic direct parametrization may have shadowed some fixtures
|
setattr(metafunc, "has_dynamic_parametrize", True)
|
||||||
# so make sure we update what the function really needs. Note that
|
|
||||||
# we didn't need to do this if only indirect dynamic parametrization
|
|
||||||
# had taken place, but anyway we did it as differentiating between direct
|
|
||||||
# and indirect requires a dirty hack.
|
|
||||||
definition = metafunc.definition
|
|
||||||
fixture_closure = definition.parent.session._fixturemanager.getfixtureclosure(
|
|
||||||
definition,
|
|
||||||
definition._fixtureinfo.initialnames,
|
|
||||||
definition._fixtureinfo.name2fixturedefs,
|
|
||||||
ignore_args=_get_direct_parametrize_args(definition) + ["request"],
|
|
||||||
)
|
|
||||||
definition._fixtureinfo.names_closure[:] = fixture_closure
|
|
||||||
|
|
||||||
|
|
||||||
class PyCollector(PyobjMixin, nodes.Collector):
|
class PyCollector(PyobjMixin, nodes.Collector):
|
||||||
|
@ -502,7 +490,7 @@ class PyCollector(PyobjMixin, nodes.Collector):
|
||||||
module=module,
|
module=module,
|
||||||
_ispytest=True,
|
_ispytest=True,
|
||||||
)
|
)
|
||||||
methods = [prune_dependency_tree_if_test_is_dynamically_parametrized]
|
methods = [check_if_test_is_dynamically_parametrized]
|
||||||
if hasattr(module, "pytest_generate_tests"):
|
if hasattr(module, "pytest_generate_tests"):
|
||||||
methods.append(module.pytest_generate_tests)
|
methods.append(module.pytest_generate_tests)
|
||||||
if cls is not None and hasattr(cls, "pytest_generate_tests"):
|
if cls is not None and hasattr(cls, "pytest_generate_tests"):
|
||||||
|
@ -516,6 +504,20 @@ class PyCollector(PyobjMixin, nodes.Collector):
|
||||||
yield Function.from_parent(self, name=name, fixtureinfo=fixtureinfo)
|
yield Function.from_parent(self, name=name, fixtureinfo=fixtureinfo)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
|
if hasattr(metafunc, "has_dynamic_parametrize"):
|
||||||
|
# add_funcarg_pseudo_fixture_def may have shadowed some fixtures
|
||||||
|
# due to dynamic direct parametrization so make sure we update
|
||||||
|
# what the function really needs. Note that we didn't need to do this if
|
||||||
|
# only indirect dynamic parametrization had taken place, but anyway we did
|
||||||
|
# it as differentiating between direct and indirect requires a dirty hack.
|
||||||
|
fixture_closure, _ = fm.getfixtureclosure(
|
||||||
|
definition,
|
||||||
|
fixtureinfo.initialnames,
|
||||||
|
fixtureinfo.name2fixturedefs,
|
||||||
|
ignore_args=_get_direct_parametrize_args(definition),
|
||||||
|
)
|
||||||
|
fixtureinfo.names_closure[:] = fixture_closure
|
||||||
|
|
||||||
for callspec in metafunc._calls:
|
for callspec in metafunc._calls:
|
||||||
subname = f"{name}[{callspec.id}]"
|
subname = f"{name}[{callspec.id}]"
|
||||||
yield Function.from_parent(
|
yield Function.from_parent(
|
||||||
|
|
|
@ -4537,7 +4537,9 @@ def test_yield_fixture_with_no_value(pytester: Pytester) -> None:
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(
|
@pytest.mark.xfail(
|
||||||
reason="arg2fixturedefs should get updated on dynamic parametrize. This gets solved by PR#11220"
|
reason="fixtureclosure should get updated before fixtures.py::pytest_generate_tests"
|
||||||
|
" and after modifying arg2fixturedefs when there's direct"
|
||||||
|
" dynamic parametrize. This gets solved by PR#11220"
|
||||||
)
|
)
|
||||||
def test_fixture_info_after_dynamic_parametrize(pytester: Pytester) -> None:
|
def test_fixture_info_after_dynamic_parametrize(pytester: Pytester) -> None:
|
||||||
pytester.makeconftest(
|
pytester.makeconftest(
|
||||||
|
@ -4575,7 +4577,7 @@ def test_fixture_info_after_dynamic_parametrize(pytester: Pytester) -> None:
|
||||||
assert fixture2 in (4, 5)
|
assert fixture2 in (4, 5)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
res = pytester.inline_run("-s")
|
res = pytester.inline_run()
|
||||||
res.assertoutcome(passed=2)
|
res.assertoutcome(passed=2)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue