From a993add78331dbebdc6bc3cec8100644eaa96402 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 17 Aug 2017 20:37:51 -0300 Subject: [PATCH 1/2] Allow tests declared as @staticmethod to use fixtures Fix #2699 --- _pytest/compat.py | 5 ++++- _pytest/fixtures.py | 6 +----- changelog/2699.bugfix | 1 + testing/python/collect.py | 14 ++++++++++++-- testing/python/fixture.py | 6 ++++++ 5 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 changelog/2699.bugfix diff --git a/_pytest/compat.py b/_pytest/compat.py index 45f9f86d4..eaa270a56 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -82,7 +82,10 @@ def num_mock_patch_args(function): return len(patchings) -def getfuncargnames(function, startindex=None): +def getfuncargnames(function, startindex=None, cls=None): + if startindex is None and cls is not None: + is_staticmethod = isinstance(cls.__dict__.get(function.__name__, None), staticmethod) + startindex = 0 if is_staticmethod else 1 # XXX merge with main.py's varnames # assert not isclass(function) realfunction = function diff --git a/_pytest/fixtures.py b/_pytest/fixtures.py index 4386500f4..f57031e1a 100644 --- a/_pytest/fixtures.py +++ b/_pytest/fixtures.py @@ -957,11 +957,7 @@ class FixtureManager: def getfixtureinfo(self, node, func, cls, funcargs=True): if funcargs and not hasattr(node, "nofuncargs"): - if cls is not None: - startindex = 1 - else: - startindex = None - argnames = getfuncargnames(func, startindex) + argnames = getfuncargnames(func, cls=cls) else: argnames = () usefixtures = getattr(func, "usefixtures", None) diff --git a/changelog/2699.bugfix b/changelog/2699.bugfix new file mode 100644 index 000000000..c5e07329b --- /dev/null +++ b/changelog/2699.bugfix @@ -0,0 +1 @@ +Allow tests declared as ``@staticmethod`` to use fixtures. diff --git a/testing/python/collect.py b/testing/python/collect.py index bd7013b44..b24c0b2fd 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -147,11 +147,21 @@ class TestClass(object): ]) def test_static_method(self, testdir): + """Support for collecting staticmethod tests (#2528, #2699)""" testdir.getmodulecol(""" + import pytest class Test(object): @staticmethod def test_something(): pass + + @pytest.fixture + def fix(self): + return 1 + + @staticmethod + def test_fix(fix): + assert fix == 1 """) result = testdir.runpytest() if sys.version_info < (2, 7): @@ -162,8 +172,8 @@ class TestClass(object): ]) else: result.stdout.fnmatch_lines([ - "*collected 1 item*", - "*1 passed in*", + "*collected 2 items*", + "*2 passed in*", ]) def test_setup_teardown_class_as_classmethod(self, testdir): diff --git a/testing/python/fixture.py b/testing/python/fixture.py index f8aef802f..06b08d68e 100644 --- a/testing/python/fixture.py +++ b/testing/python/fixture.py @@ -29,10 +29,16 @@ def test_getfuncargnames(): def f(self, arg1, arg2="hello"): pass + @staticmethod + def static(arg1, arg2): + pass + assert fixtures.getfuncargnames(A().f) == ('arg1',) if sys.version_info < (3, 0): assert fixtures.getfuncargnames(A.f) == ('arg1',) + assert fixtures.getfuncargnames(A.static, cls=A) == ('arg1', 'arg2') + class TestFillFixtures(object): def test_fillfuncargs_exposed(self): From 1fc185b6405e63df37eb16bbbc62c0ed50d84f21 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 5 Sep 2017 19:28:39 -0300 Subject: [PATCH 2/2] Add comment about possible future refactoring in the fixture mechanism --- _pytest/compat.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/_pytest/compat.py b/_pytest/compat.py index eaa270a56..e980128ed 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -83,6 +83,11 @@ def num_mock_patch_args(function): def getfuncargnames(function, startindex=None, cls=None): + """ + @RonnyPfannschmidt: This function should be refactored when we revisit fixtures. The + fixture mechanism should ask the node for the fixture names, and not try to obtain + directly from the function object well after collection has occurred. + """ if startindex is None and cls is not None: is_staticmethod = isinstance(cls.__dict__.get(function.__name__, None), staticmethod) startindex = 0 if is_staticmethod else 1