parent
eca93db05b
commit
9fbd67dd4b
1
AUTHORS
1
AUTHORS
|
@ -225,6 +225,7 @@ Marcin Bachry
|
|||
Marco Gorelli
|
||||
Mark Abramowitz
|
||||
Mark Dickinson
|
||||
Marko Pacak
|
||||
Markus Unterwaditzer
|
||||
Martijn Faassen
|
||||
Martin Altmayer
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Test methods decorated with ``@classmethod`` can now be discovered as tests, following the same rules as normal methods. This fills the gap that static methods were discoverable as tests but not class methods.
|
|
@ -50,8 +50,8 @@ Conventions for Python test discovery
|
|||
* In those directories, search for ``test_*.py`` or ``*_test.py`` files, imported by their `test package name`_.
|
||||
* From those files, collect test items:
|
||||
|
||||
* ``test`` prefixed test functions or methods outside of class
|
||||
* ``test`` prefixed test functions or methods inside ``Test`` prefixed test classes (without an ``__init__`` method)
|
||||
* ``test`` prefixed test functions or methods outside of class.
|
||||
* ``test`` prefixed test functions or methods inside ``Test`` prefixed test classes (without an ``__init__`` method). Methods decorated with ``@staticmethod`` and ``@classmethods`` are also considered.
|
||||
|
||||
For examples of how to customize your test discovery :doc:`/example/pythoncollection`.
|
||||
|
||||
|
|
|
@ -403,8 +403,8 @@ class PyCollector(PyobjMixin, nodes.Collector):
|
|||
|
||||
def istestfunction(self, obj: object, name: str) -> bool:
|
||||
if self.funcnamefilter(name) or self.isnosetest(obj):
|
||||
if isinstance(obj, staticmethod):
|
||||
# staticmethods need to be unwrapped.
|
||||
if isinstance(obj, (staticmethod, classmethod)):
|
||||
# staticmethods and classmethods need to be unwrapped.
|
||||
obj = safe_getattr(obj, "__func__", False)
|
||||
return callable(obj) and fixtures.getfixturemarker(obj) is None
|
||||
else:
|
||||
|
|
|
@ -416,7 +416,7 @@ def test_function_instance(pytester: Pytester) -> None:
|
|||
def test_static(): pass
|
||||
"""
|
||||
)
|
||||
assert len(items) == 3
|
||||
assert len(items) == 4
|
||||
assert isinstance(items[0], Function)
|
||||
assert items[0].name == "test_func"
|
||||
assert items[0].instance is None
|
||||
|
@ -424,6 +424,6 @@ def test_function_instance(pytester: Pytester) -> None:
|
|||
assert items[1].name == "test_method"
|
||||
assert items[1].instance is not None
|
||||
assert items[1].instance.__class__.__name__ == "TestIt"
|
||||
assert isinstance(items[2], Function)
|
||||
assert items[2].name == "test_static"
|
||||
assert items[2].instance is None
|
||||
assert isinstance(items[3], Function)
|
||||
assert items[3].name == "test_static"
|
||||
assert items[3].instance is None
|
||||
|
|
|
@ -735,6 +735,20 @@ class Test_genitems:
|
|||
assert s.endswith("test_example_items1.testone")
|
||||
print(s)
|
||||
|
||||
def test_classmethod_is_discovered(self, pytester: Pytester) -> None:
|
||||
"""Test that classmethods are discovered"""
|
||||
p = pytester.makepyfile(
|
||||
"""
|
||||
class TestCase:
|
||||
@classmethod
|
||||
def test_classmethod(cls) -> None:
|
||||
pass
|
||||
"""
|
||||
)
|
||||
items, reprec = pytester.inline_genitems(p)
|
||||
ids = [x.getmodpath() for x in items] # type: ignore[attr-defined]
|
||||
assert ids == ["TestCase.test_classmethod"]
|
||||
|
||||
def test_class_and_functions_discovery_using_glob(self, pytester: Pytester) -> None:
|
||||
"""Test that Python_classes and Python_functions config options work
|
||||
as prefixes and glob-like patterns (#600)."""
|
||||
|
|
Loading…
Reference in New Issue