diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 73d77f978..118e7b72b 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -163,6 +163,7 @@ def getfuncargnames( and not isinstance( inspect.getattr_static(cls, name, default=None), staticmethod ) + and not hasattr(function, "__self__") ): arg_names = arg_names[1:] # Remove any names that will be replaced with mocks. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index e2c81e7eb..02300a0aa 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -507,7 +507,7 @@ class PyCollector(PyobjMixin, nodes.Collector): for callspec in metafunc._calls: subname = f"{name}[{callspec.id}]" - node = Function.from_parent( + yield Function.from_parent( self, name=subname, callspec=callspec, @@ -515,18 +515,6 @@ class PyCollector(PyobjMixin, nodes.Collector): keywords={callspec.id: True}, originalname=name, ) - # if usefixtures is added via a parameter, then there will be - # fixtures missing from the node.fixturenames - callspec_usefixtures = tuple( - arg - for mark in node.iter_markers(name="usefixtures") - for arg in mark.args - if arg not in node.fixturenames - ) - if callspec_usefixtures: - # node.fixturenames must be unique for this parameter - node.fixturenames = [*node.fixturenames, *callspec_usefixtures] - yield node def importtestmodule( @@ -1811,9 +1799,13 @@ class Function(PyobjMixin, nodes.Item): if keywords: self.keywords.update(keywords) + fm = self.session._fixturemanager + fixtureinfo_ = fm.getfixtureinfo(self, self.obj, self.cls) if fixtureinfo is None: - fm = self.session._fixturemanager - fixtureinfo = fm.getfixtureinfo(self, self.obj, self.cls) + fixtureinfo = fixtureinfo_ + elif set(fixtureinfo_.names_closure) != set(fixtureinfo.names_closure): + fixtureinfo_.name2fixturedefs.update(fixtureinfo.name2fixturedefs) + fixtureinfo = fixtureinfo_ self._fixtureinfo: FuncFixtureInfo = fixtureinfo self.fixturenames = fixtureinfo.names_closure self._initrequest()