diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index d5f9ad2d3f0..8a701db1aff 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -823,6 +823,27 @@ def __init__( self.ids = ids self._finalizers = [] + @property + def argnames(self): + return self._argnames + + @argnames.setter + def argnames(self, value): + # TODO: Check who calls this setter + self._argnames = value + + @property + def usefixtureargnames(self): + markers = getattr(self.func, "pytestmark", []) + usefixtureargs = tuple( + itertools.chain.from_iterable( + mark.args + for mark in markers + if getattr(mark, "name", None) == "usefixtures" + ) + ) + return usefixtureargs + def addfinalizer(self, finalizer): self._finalizers.append(finalizer) @@ -906,10 +927,12 @@ def resolve_fixture_function(fixturedef, request): def pytest_fixture_setup(fixturedef, request): """ Execution of fixture setup. """ kwargs = {} - for argname in fixturedef.argnames: + for argname in fixturedef.argnames + fixturedef.usefixtureargnames: fixdef = request._get_active_fixturedef(argname) result, arg_cache_key, exc = fixdef.cached_result request._check_scope(argname, request.scope, fixdef.scope) + if argname not in fixturedef.argnames: + continue kwargs[argname] = result fixturefunc = resolve_fixture_function(fixturedef, request) diff --git a/testing/test_usefixtures_in_fixtures.py b/testing/test_usefixtures_in_fixtures.py new file mode 100644 index 00000000000..078b21b5cbf --- /dev/null +++ b/testing/test_usefixtures_in_fixtures.py @@ -0,0 +1,30 @@ +import pytest + + +@pytest.fixture +def state(): + return {} + + +@pytest.fixture +def setup_for_foo(state): + state["setup"] = True + + +@pytest.fixture +def foo_explicit(setup_for_foo, state): + return state["setup"] is True + + +def test_foo_explicit(foo_explicit): + assert foo_explicit + + +@pytest.fixture +@pytest.mark.usefixtures("setup_for_foo") +def foo_implicit(state): + return state["setup"] is True + + +def test_foo_implicit(foo_implicit): + assert foo_implicit