diff --git a/AUTHORS b/AUTHORS index 20798f309..abac9f010 100644 --- a/AUTHORS +++ b/AUTHORS @@ -29,6 +29,7 @@ Andy Freeland Anthon van der Neut Anthony Shaw Anthony Sottile +Anton Grinevich Anton Lodder Antony Lee Arel Cordero diff --git a/changelog/8061.bugfix.rst b/changelog/8061.bugfix.rst new file mode 100644 index 000000000..2c8980fb3 --- /dev/null +++ b/changelog/8061.bugfix.rst @@ -0,0 +1 @@ +Fixed failing staticmethod test cases if they are inherited from a parent test class. diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 0b87c7bbc..b354fcb3f 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -163,7 +163,12 @@ def getfuncargnames( # it's passed as an unbound method or function, remove the first # parameter name. if is_method or ( - cls and not isinstance(cls.__dict__.get(name, None), staticmethod) + # 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 isinstance( + inspect.getattr_static(cls, name, default=None), staticmethod + ) ): arg_names = arg_names[1:] # Remove any names that will be replaced with mocks. diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 862a65abe..12340e690 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -59,6 +59,20 @@ def test_getfuncargnames_staticmethod(): assert getfuncargnames(A.static, cls=A) == ("arg1", "arg2") +def test_getfuncargnames_staticmethod_inherited() -> None: + """Test getfuncargnames for inherited staticmethods (#8061)""" + + class A: + @staticmethod + def static(arg1, arg2, x=1): + raise NotImplementedError() + + class B(A): + pass + + assert getfuncargnames(B.static, cls=B) == ("arg1", "arg2") + + def test_getfuncargnames_partial(): """Check getfuncargnames for methods defined with functools.partial (#5701)""" import functools