Skip to content

Inconsistent support for staticmethod/classmethod #10525

@Jasha10

Description

@Jasha10

Pytest discovery & running of staticmethods/classmethods is inconsistent. Here's an example:

import pytest

class TestFoo:
    # passes:
    @staticmethod
    def test_staticmethod() -> None:
        foo = 0
        assert foo < 3

    # warning: cannot collect 'test_staticmethod_inner' because it is not a function.
    @pytest.mark.parametrize("foo", [1, 2])
    @staticmethod
    def test_staticmethod_inner(foo: int) -> None:
        assert foo < 3

    # passes:
    @staticmethod
    @pytest.mark.parametrize("foo", [1, 2])
    def test_staticmethod_outer(foo: int) -> None:
        assert foo < 3

    # silently fails to run
    @classmethod
    def test_classmethod(cls) -> None:
        foo = 0
        assert foo < 3

    # warning: cannot collect 'test_classmethod_inner' because it is not a function.
    @pytest.mark.parametrize("foo", [1, 2])
    @classmethod
    def test_classmethod_inner(cls, foo: int) -> None:
        assert foo < 3

    # silently fails to run
    @classmethod
    @pytest.mark.parametrize("foo", [1, 2])
    def test_classmethod_outer(cls, foo: int) -> None:
        assert foo < 3

The most worrysome cases are test_classmethod and test_classmethod_outer, which are not discovered by pytest. I think that there should at least be a warning or error to alert the user that their test code cannot be run.

Here's the full output from running `pytest -v`:
$ pytest tmp.py -v
======================== test session starts =========================
platform linux -- Python 3.9.15, pytest-7.2.0, pluggy-1.0.0 -- /home/homestar/tmp2/tmp_venv/bin/python3
cachedir: .pytest_cache
rootdir: /home/homestar/tmp2
collected 3 items

tmp.py::TestFoo::test_staticmethod PASSED                      [ 33%]
tmp.py::TestFoo::test_staticmethod_outer[1] PASSED             [ 66%]
tmp.py::TestFoo::test_staticmethod_outer[2] PASSED             [100%]

========================== warnings summary ==========================
tmp_venv/lib/python3.9/site-packages/_pytest/mark/structures.py:347
  /home/homestar/tmp2/tmp_venv/lib/python3.9/site-packages/_pytest/mark/structures.py:347: PytestCollectionWarning: cannot collect 'test_staticmethod_inner' because it is not a function.
    def __call__(self, *args: object, **kwargs: object):

tmp_venv/lib/python3.9/site-packages/_pytest/mark/structures.py:347
  /home/homestar/tmp2/tmp_venv/lib/python3.9/site-packages/_pytest/mark/structures.py:347: PytestCollectionWarning: cannot collect 'test_classmethod_inner' because it is not a function.
    def __call__(self, *args: object, **kwargs: object):

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=================== 3 passed, 2 warnings in 0.00s ====================

python v3.9.15, pytest v7.2.0, ubuntu 20.04

Output of `pip list`:
$ pip list
Package        Version
-------------- -------
attrs          22.1.0
exceptiongroup 1.0.4
iniconfig      1.1.1
packaging      21.3
pip            22.0.4
pluggy         1.0.0
pyparsing      3.0.9
pytest         7.2.0
setuptools     58.1.0
tomli          2.0.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: collectionrelated to the collection phasetype: bugproblem that needs to be addressed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions