From 08511f0f515cd50e83047bbd22a64120a3bd01cd Mon Sep 17 00:00:00 2001 From: Alessio Bogon Date: Sat, 24 Aug 2019 17:23:01 +0200 Subject: [PATCH 1/2] Basic acceptance test --- testing/test_usefixtures_in_fixtures.py | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 testing/test_usefixtures_in_fixtures.py diff --git a/testing/test_usefixtures_in_fixtures.py b/testing/test_usefixtures_in_fixtures.py new file mode 100644 index 00000000000..9cdf4c946a6 --- /dev/null +++ b/testing/test_usefixtures_in_fixtures.py @@ -0,0 +1,29 @@ +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.mark.usefixtures('setup_for_foo') +@pytest.fixture +def foo_implicit(state): + return state['setup'] is True + + +def test_foo_implicit(foo_implicit): + assert foo_implicit From 9086a18f791b92551fd244f8ebec67fc4e82aa78 Mon Sep 17 00:00:00 2001 From: Alessio Bogon Date: Sat, 24 Aug 2019 18:25:20 +0200 Subject: [PATCH 2/2] Basic working implementation. Defenitively not up to standards --- src/_pytest/fixtures.py | 25 ++++++++++++++++++++++++- testing/test_usefixtures_in_fixtures.py | 9 +++++---- 2 files changed, 29 insertions(+), 5 deletions(-) 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 index 9cdf4c946a6..078b21b5cbf 100644 --- a/testing/test_usefixtures_in_fixtures.py +++ b/testing/test_usefixtures_in_fixtures.py @@ -1,5 +1,6 @@ import pytest + @pytest.fixture def state(): return {} @@ -7,22 +8,22 @@ def state(): @pytest.fixture def setup_for_foo(state): - state['setup'] = True + state["setup"] = True @pytest.fixture def foo_explicit(setup_for_foo, state): - return state['setup'] is True + return state["setup"] is True def test_foo_explicit(foo_explicit): assert foo_explicit -@pytest.mark.usefixtures('setup_for_foo') @pytest.fixture +@pytest.mark.usefixtures("setup_for_foo") def foo_implicit(state): - return state['setup'] is True + return state["setup"] is True def test_foo_implicit(foo_implicit):