From ee3ef47a157f6d7b6b907ad4cead018f5ebd16ca Mon Sep 17 00:00:00 2001 From: Minh Dau Date: Tue, 15 Sep 2026 18:20:46 -0400 Subject: [PATCH] Fix fixture discovery for bound methods in custom collectors --- AUTHORS | 1 + changelog/6750.bugfix.rst | 1 + src/_pytest/compat.py | 1 + testing/python/fixtures.py | 46 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+) create mode 100644 changelog/6750.bugfix.rst diff --git a/AUTHORS b/AUTHORS index ad4c2093892..bdc6a99c0cf 100644 --- a/AUTHORS +++ b/AUTHORS @@ -346,6 +346,7 @@ Mike Lundy Mike Ma Milan Lesnek minbang930 +Minh Dau Miro HronĨok Mulat Mekonen mrbean-bremen diff --git a/changelog/6750.bugfix.rst b/changelog/6750.bugfix.rst new file mode 100644 index 00000000000..74c008da1e8 --- /dev/null +++ b/changelog/6750.bugfix.rst @@ -0,0 +1 @@ +Fix fixture argument discovery for custom collectors that pass bound methods to :class:`pytest.Function`. diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 93aec228c7c..fc4cbd33f59 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -162,6 +162,7 @@ def getfuncargnames( # Not using `getattr` because we don't want to resolve the staticmethod. # Not using `cls.__dict__` because we want to check the entire MRO. cls + and not inspect.ismethod(function) and not isinstance( inspect.getattr_static(cls, name, default=None), staticmethod ) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 8e779a93d76..36e414f2a1f 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -69,6 +69,52 @@ def k(self, /, arg1, *, arg2, arg3="hello"): assert getfuncargnames(A().k) == ("arg1", "arg2") +def test_bound_method_fixtures_custom_collector(pytester: Pytester) -> None: + """Custom collectors can supply already-bound methods (#6750).""" + pytester.makeconftest( + """ + import pytest + + def pytest_pycollect_makeitem(collector, name, obj): + if isinstance(collector, pytest.Class) and name.startswith("test_"): + return pytest.Function.from_parent( + collector, + name=name, + callobj=getattr(collector.newinstance(), name), + ) + """ + ) + pytester.makepyfile( + """ + import pytest + + @pytest.fixture + def value(): + return 42 + + class TestBound: + def test_instance(self, value): + assert value == 42 + + def test_positional_only_receiver(self, /, value): + assert value == 42 + + def test_keyword_only_fixture(self, *, value): + assert value == 42 + + @classmethod + def test_classmethod(cls, value): + assert value == 42 + + @staticmethod + def test_staticmethod(value): + assert value == 42 + """ + ) + result = pytester.runpytest() + result.assert_outcomes(passed=5) + + def test_getfuncargnames_staticmethod(): """Test getfuncargnames for staticmethods"""