Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/3225.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
A non-autouse fixture overriding an autouse one no longer runs automatically.
19 changes: 17 additions & 2 deletions src/_pytest/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -1938,14 +1938,29 @@ def pytest_collection_finish(self) -> None:

def _getautousenames(self, node: nodes.Node) -> Iterator[str]:
"""Return the names of autouse fixtures visible to node."""
usefixtures_ini = set(self.config.getini("usefixtures"))
for parentnode in node.listchain():
basenames = self._node_autousenames.get(parentnode)
if basenames:
yield from basenames
for name in basenames:
if name in usefixtures_ini or self._is_autouse(name, node):
yield name
# Legacy fallback: check string-based nodeid autouse names.
nodeid_basenames = self._nodeid_autousenames.get(parentnode.nodeid)
if nodeid_basenames:
yield from nodeid_basenames
for name in nodeid_basenames:
if self._is_autouse(name, node):
yield name

def _is_autouse(self, name: str, node: nodes.Node) -> bool:
"""Whether the fixture resolved for name is itself autouse.

A non-autouse override cancels the autouse fixture it shadows (#3225).
"""
fixturedefs = self.getfixturedefs(name, node)
if not fixturedefs:
return True
return fixturedefs[-1]._autouse

def _getusefixturesnames(self, node: nodes.Item) -> Iterator[str]:
"""Return the names of usefixtures fixtures visible to node."""
Expand Down
33 changes: 33 additions & 0 deletions testing/python/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -2560,6 +2560,39 @@ def test_hello(arg1):
reprec = pytester.inline_run()
reprec.assertoutcome(passed=1)

def test_autouse_cancelled_by_non_autouse_override(
self, pytester: Pytester
) -> None:
"""A non-autouse override cancels the autouse fixture it shadows (#3225)."""
pytester.makeconftest(
"""
import pytest

@pytest.fixture(autouse=True)
def foo():
pass
"""
)
pytester.makepyfile(
"""
import pytest

@pytest.fixture()
def foo():
assert False

def test_bar(foo):
pass

def test_baz():
pass
"""
)
result = pytester.runpytest()
result.assert_outcomes(passed=1, errors=1)
result = pytester.runpytest("-o", "usefixtures=foo")
result.assert_outcomes(errors=2)

@pytest.mark.parametrize("param1", ["", "params=[1]"], ids=["p00", "p01"])
@pytest.mark.parametrize("param2", ["", "params=[1]"], ids=["p10", "p11"])
def test_ordering_dependencies_torndown_first(
Expand Down