如果定义了构造函数,则 py.test 将跳过测试类

我有以下通过 py.test 运行的单元测试代码。 仅仅是构造函数的存在就会使整个类在运行时跳过 Py.test-v-s

收集了0个项目/1个跳过

有人能给我解释一下 py.test 的这种行为吗?

我对理解 py.test 行为很感兴趣,我知道不需要构造函数。

谢谢, Zdenek

class TestClassName(object):
def __init__(self):
pass


def setup_method(self, method):
print "setup_method called"


def teardown_method(self, method):
print "teardown_method called"


def test_a(self):
print "test_a called"
assert 1 == 1


def test_b(self):
print "test_b called"
assert 1 == 1
55243 次浏览

The documentation for py.test says that py.test implements the following standard test discovery:

  • collection starts from the initial command line arguments which may be directories, filenames or test ids. recurse into directories, unless they match norecursedirs
  • test_*.py or *_test.py files, imported by their package name.
  • Test prefixed test classes (without an __init__ method) [<-- notice this one here]
  • test_ prefixed test functions or methods are test items

So it's not that the constructor isn't needed, py.test just ignores classes that have a constructor. There is also a guide for changing the standard test discovery.

As already mentioned in the answer by Matti Lyra py.test purposely skips classes which have a constructor. The reason for this is that classes are only used for structural reasons in py.test and do not have any inherent behaviour, while when actually writing code it is the opposite and much rarer to not have an .__init__() method for a class. So in practice skipping a class with a constructor will likely be what was desired, usually it is just a class which happens to have a conflicting name.

Lastly py.test needs to instantiate the class in order to execute the tests. If the constructor takes any arguments it can't instantiate it, so again skipping is the right thing to do.

All the above answers clearly explain the underlying cause, I just thought to share my experience and workaround the warnings.

I got my test to work without the warnings by aliasing the imported Class

from app.core.utils import model_from_meta
from app.core.models import Panel, TestType as _TestType
from app.core.serializers import PanelSerializer, TestType as _TestTypeSerializer




def test_model_from_meta():
assert (Panel is model_from_meta(PanelSerializer))
assert (_TestType is model_from_meta(_TestTypeSerializer))

After importing the class using aliases the warnings no longer get printed

I hope this helps someone.

In my case, I just so happened to have a parameter's class names TestParams, which conflicts with pytest looking for classes beginning with the name test....

Solution: rename your own class

Source