Skip to content
Closed
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
16 changes: 15 additions & 1 deletion src/_pytest/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -1933,7 +1933,9 @@ def _getautousenames(self, node: nodes.Node) -> Iterator[str]:
basenames = self._node_autousenames.get(parentnode)
if basenames:
yield from basenames
# Legacy fallback: check string-based nodeid autouse names.
# For Directory nodes, also check by nodeid in case a fresh
# Directory was created and the autouse fixtures were registered
# to a Directory with the same nodeid (#14964).
nodeid_basenames = self._nodeid_autousenames.get(parentnode.nodeid)
if nodeid_basenames:
yield from nodeid_basenames
Expand Down Expand Up @@ -2116,6 +2118,10 @@ def _register_fixture(
if autouse:
if node is not NOTSET:
self._node_autousenames.setdefault(node, []).append(name)
# Also store by nodeid for Directory nodes to handle fresh
# node instances when re-collecting (#14964).
if isinstance(node, nodes.Directory):
self._nodeid_autousenames.setdefault(node.nodeid, []).append(name)
elif nodeid is not NOTSET and nodeid is not None:
# Legacy: plugin passed nodeid string without node reference.
self._nodeid_autousenames.setdefault(nodeid, []).append(name)
Expand Down Expand Up @@ -2370,6 +2376,14 @@ def _matchfactories(
# Node-based matching: check if fixture's node is a parent
if fixturedef.node in parent_nodes:
yield fixturedef
elif any(
isinstance(p, nodes.Directory) and fixturedef.baseid == p.nodeid
for p in parent_nodes
):
# For Directory nodes, also check by nodeid in case a fresh
# Directory was created and the fixture's node is not in the
# parent chain but the baseid matches (#14964).
yield fixturedef
elif fixturedef.baseid in parentnodeids:
# Fallback to string-based matching for legacy/plugins
yield fixturedef
Expand Down