diff --git a/AUTHORS b/AUTHORS index 1dbef3d5d..e355f01e0 100644 --- a/AUTHORS +++ b/AUTHORS @@ -23,6 +23,7 @@ Andras Tim Andrea Cimatoribus Andreas Zeidler Andrey Paramonov +Andrzej Klajnert Andrzej Ostrowski Andy Freeland Anthon van der Neut diff --git a/changelog/570.bugfix.rst b/changelog/570.bugfix.rst new file mode 100644 index 000000000..8936ff96a --- /dev/null +++ b/changelog/570.bugfix.rst @@ -0,0 +1 @@ +Fix the scope behavior with indirect fixtures. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index d5f9ad2d3..9a904758f 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -859,7 +859,7 @@ class FixtureDef: if argname != "request": fixturedef.addfinalizer(functools.partial(self.finish, request=request)) - my_cache_key = request.param_index + my_cache_key = self.cache_key(request) cached_result = getattr(self, "cached_result", None) if cached_result is not None: result, cache_key, err = cached_result @@ -877,6 +877,9 @@ class FixtureDef: hook = self._fixturemanager.session.gethookproxy(request.node.fspath) return hook.pytest_fixture_setup(fixturedef=self, request=request) + def cache_key(self, request): + return request.param_index if not hasattr(request, "param") else request.param + def __repr__(self): return "".format( self.argname, self.scope, self.baseid @@ -913,7 +916,7 @@ def pytest_fixture_setup(fixturedef, request): kwargs[argname] = result fixturefunc = resolve_fixture_function(fixturedef, request) - my_cache_key = request.param_index + my_cache_key = fixturedef.cache_key(request) try: result = call_fixture_func(fixturefunc, request, kwargs) except TEST_OUTCOME: diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 1f383e752..a129aa582 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -449,7 +449,8 @@ class TestFillFixtures: "*ERROR at setup of test_lookup_error*", " def test_lookup_error(unknown):*", "E fixture 'unknown' not found", - "> available fixtures:*a_fixture,*b_fixture,*c_fixture,*d_fixture*monkeypatch,*", # sorted + "> available fixtures:*a_fixture,*b_fixture,*c_fixture,*d_fixture*monkeypatch,*", + # sorted "> use 'py*test --fixtures *' for help on them.", "*1 error*", ] @@ -4009,3 +4010,45 @@ def test_fixture_named_request(testdir): " *test_fixture_named_request.py:5", ] ) + + +def test_indirect_fixture(testdir): + testdir.makepyfile( + """ + from collections import Counter + + import pytest + + + @pytest.fixture(scope="session") + def fixture_1(request, count=Counter()): + count[request.param] += 1 + yield count[request.param] + + + @pytest.fixture(scope="session") + def fixture_2(request): + yield request.param + + + scenarios = [ + ("a", "a1"), + ("a", "a2"), + ("b", "b1"), + ("b", "b2"), + ("c", "c1"), + ("c", "c2"), + ] + + + @pytest.mark.parametrize( + "fixture_1,fixture_2", scenarios, indirect=["fixture_1", "fixture_2"] + ) + def test_it(fixture_1, fixture_2): + assert fixture_1 == 1 + assert fixture_2[1] in ("1", "2") + + """ + ) + result = testdir.runpytest() + result.assert_outcomes(passed=6)