Skip to content

Commit

Permalink
Allow ovewriting a parametrized fixture while reusing the parent fixt…
Browse files Browse the repository at this point in the history
…ure's value

Fix pytest-dev#1953
  • Loading branch information
nicoddemus committed Sep 10, 2020
1 parent 9c0e0c7 commit edbcabf
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 5 deletions.
20 changes: 20 additions & 0 deletions changelog/1953.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Fix error when overwriting a fixture, reusing the original fixture value, when the overwritten fixture is parameterized:

.. code-block:: python
# conftest.py
import pytest
@pytest.fixture(params=[1, 2])
def foo(request):
return request.param
# test_foo.py
import pytest
@pytest.fixture
def foo(foo):
return foo * 2
11 changes: 6 additions & 5 deletions src/_pytest/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -1530,9 +1530,8 @@ def sort_by_scope(arg_name: str) -> int:

def pytest_generate_tests(self, metafunc: "Metafunc") -> None:
for argname in metafunc.fixturenames:
faclist = metafunc._arg2fixturedefs.get(argname)
if faclist:
fixturedef = faclist[-1]
fixture_defs = metafunc._arg2fixturedefs.get(argname, ())
for fixturedef in reversed(fixture_defs):
if fixturedef.params is not None:
markers = list(metafunc.definition.iter_markers("parametrize"))
for parametrize_mark in markers:
Expand All @@ -1555,8 +1554,10 @@ def pytest_generate_tests(self, metafunc: "Metafunc") -> None:
scope=fixturedef.scope,
ids=fixturedef.ids,
)
else:
continue # Will raise FixtureLookupError at setup time.
# stop if the current fixturedef doesn't also depend on its own
# argname, in case it is being overwritten (#1953)
if argname not in fixturedef.argnames:
break

def pytest_collection_modifyitems(self, items: "List[nodes.Item]") -> None:
# Separate parametrized setups.
Expand Down
28 changes: 28 additions & 0 deletions testing/python/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,34 @@ def test_spam(spam):
result = testdir.runpytest(testfile)
result.stdout.fnmatch_lines(["*3 passed*"])

def test_override_fixture_reusing_with_params(self, testdir):
"""Override a fixture at a lower level, reusing the higher-level fixture that
is parametrized (#1953).
"""
testdir.makeconftest(
"""
import pytest
@pytest.fixture(params=[1, 2])
def foo(request):
return request.param
"""
)
testdir.makepyfile(
"""
import pytest
@pytest.fixture
def foo(foo):
return foo * 2
def test_spam(foo):
assert foo in (2, 4)
"""
)
result = testdir.runpytest()
result.stdout.fnmatch_lines(["*2 passed*"])

def test_autouse_fixture_plugin(self, testdir):
# A fixture from a plugin has no baseid set, which screwed up
# the autouse fixture handling.
Expand Down

0 comments on commit edbcabf

Please sign in to comment.