fixtures: match fixtures based on actual node hierarchy, not textual nodeids

Refs #11662.

--- Problem

Each fixture definition has a "visibility", the `FixtureDef.baseid`
attribute. This is nodeid-like string. When a certain `node` requests a
certain fixture name, we match node's nodeid against the fixture
definitions with this name.

The matching currently happens on the *textual* representation of the
nodeid - we split `node.nodeid` to its "parent nodeids" and then check
if the fixture's `baseid` is in there.

While this has worked so far, we really should try to avoid textual
manipulation of nodeids as much as possible. It has also caused problem
in an odd case of a `Package` in the root directory: the `Package` gets
nodeid `.`, while a `Module` in it gets nodeid `test_module.py`. And
textually, `.` is not a parent of `test_module.py`.

--- Solution

Avoid this entirely by just checking the node hierarchy itself. This is
made possible by the fact that we now have proper `Directory` nodes
(`Dir` or `Package`) for the entire hierarchy.

Also do the same for `_getautousenames` which is a similar deal.

The `iterparentnodeids` function is no longer used and is removed.
This commit is contained in:
Ran Benita
2024-01-06 13:12:02 +02:00
parent c2a4a8d518
commit 992d0f082f
7 changed files with 40 additions and 92 deletions

View File

@@ -1574,7 +1574,7 @@ class TestFixtureManagerParseFactories:
"""
def test_hello(item, fm):
for name in ("fm", "hello", "item"):
faclist = fm.getfixturedefs(name, item.nodeid)
faclist = fm.getfixturedefs(name, item)
assert len(faclist) == 1
fac = faclist[0]
assert fac.func.__name__ == name
@@ -1598,7 +1598,7 @@ class TestFixtureManagerParseFactories:
def hello(self, request):
return "class"
def test_hello(self, item, fm):
faclist = fm.getfixturedefs("hello", item.nodeid)
faclist = fm.getfixturedefs("hello", item)
print(faclist)
assert len(faclist) == 3
@@ -1804,7 +1804,7 @@ class TestAutouseDiscovery:
"""
from _pytest.pytester import get_public_names
def test_check_setup(item, fm):
autousenames = list(fm._getautousenames(item.nodeid))
autousenames = list(fm._getautousenames(item))
assert len(get_public_names(autousenames)) == 2
assert "perfunction2" in autousenames
assert "perfunction" in autousenames