Skip to content

Commit

Permalink
Merge pull request #5798 from aklajnert/570-indirect-fixtures
Browse files Browse the repository at this point in the history
Fix the scope behavior with indirect fixtures
  • Loading branch information
nicoddemus committed Aug 30, 2019
2 parents 01082fe + 35b3b10 commit 4e59455
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 3 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Andras Tim
Andrea Cimatoribus
Andreas Zeidler
Andrey Paramonov
Andrzej Klajnert
Andrzej Ostrowski
Andy Freeland
Anthon van der Neut
Expand Down
2 changes: 2 additions & 0 deletions changelog/570.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fixed long standing issue where fixture scope was not respected when indirect fixtures were used during
parametrization.
7 changes: 5 additions & 2 deletions src/_pytest/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ def execute(self, request):
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
Expand All @@ -877,6 +877,9 @@ def execute(self, request):
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 "<FixtureDef argname={!r} scope={!r} baseid={!r}>".format(
self.argname, self.scope, self.baseid
Expand Down Expand Up @@ -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:
Expand Down
55 changes: 54 additions & 1 deletion testing/python/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,8 @@ def test_lookup_error(unknown):
"*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*",
]
Expand Down Expand Up @@ -4009,3 +4010,55 @@ def test_fixture_named_request(testdir):
" *test_fixture_named_request.py:5",
]
)


def test_indirect_fixture_does_not_break_scope(testdir):
"""Ensure that fixture scope is respected when using indirect fixtures (#570)"""
testdir.makepyfile(
"""
import pytest
instantiated = []
@pytest.fixture(scope="session")
def fixture_1(request):
instantiated.append(("fixture_1", request.param))
@pytest.fixture(scope="session")
def fixture_2(request):
instantiated.append(("fixture_2", 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_create_fixtures(fixture_1, fixture_2):
pass
def test_check_fixture_instantiations():
assert instantiated == [
('fixture_1', 'A'),
('fixture_2', 'a1'),
('fixture_2', 'a2'),
('fixture_1', 'B'),
('fixture_2', 'b1'),
('fixture_2', 'b2'),
('fixture_1', 'C'),
('fixture_2', 'c1'),
('fixture_2', 'c2'),
]
"""
)
result = testdir.runpytest()
result.assert_outcomes(passed=7)

0 comments on commit 4e59455

Please sign in to comment.