为什么派生类中的测试会重新运行父类测试?

时间:2015-11-03 15:48:39

标签: python pytest python-unittest nosetests

当测试设置中存在显着重叠时,它可以使DRY保持使用继承。但这会导致测试执行不必要重复的问题:

from unittest import TestCase

class TestPotato(TestCase):
    def test_in_parent(self):
        print 'in parent'

class TestSpud(TestPotato):
    def test_in_child(self):
        print 'in child'

测试此模块会运行test_in_parent两次。

$ python -m unittest example
in parent
.in child
.in parent
.
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

为什么呢?这是设计的吗?可以通过以某种方式配置测试运行器来禁用它吗?

我可以通过将setup移动到一个非发现的类来解决这个问题,然后使用多个继承,但它看起来有点hacky和不必要。

注意:在其他参与者中出现同样的问题,例如鼻子(nosetests -s example.py)和pytest(py.test example.py

3 个答案:

答案 0 :(得分:4)

测试运行者查找以test开头的所有方法。子类中存在继承的方法 - 因此它们被检测为要运行的测试。 为避免这种情况,您应该在父类中提取公共代码,并且不继承任何实际测试。

from unittest import TestCase

class PotatoTestTemplate(TestCase):
    def setUp():
        pass

class PotatoTest1(PotatoTestTemplate):
    def test1(self):
        pass

class PotatoTest2(PotatoTestTemplate):
    def test1(self):
        pass

答案 1 :(得分:1)

我见过人们使用的另一种解决方法是嵌套类不会作为鼻子测试的一部分运行,例如。

from unittest import TestCase
class NotTested:
    class TestPotato(TestCase):
        def test_in_parent(self):
            print 'in parent'

class TestSpud(NotTested.TestPotato):
    def test_in_child(self):
        print 'in child'

我尝试失败的解决方法是使用多重继承,因此TestPotato类扩展了对象,TestSpud确实扩展了TestCase和TestPotato 例如

from unittest import TestCase

class TestPotato(object):
    def test_in_parent(self): 
        # still gets ran twice because
        # nosetests runs anything that starts with test_* :(
         print 'in parent'

class TestSpud(TestCase, TestPotato):
    def test_in_child(self):
        print 'in child'

但实际上这对我不起作用,我希望它能做到,因为你不需要添加代码嵌套......但它看起来像是使用multiple inheritance is bad anyway

答案 2 :(得分:1)

如果您需要来自不同测试类的测试setUp,则可以执行以下操作:

from unittest import TestCase

class TestPotato(TestCase):
    def setUp(self):
        print('fixtures here')

    def test_in_parent(self):
        print 'in parent'


class TestSpud(TestCase):
    def setUp(self):
        TestPotato.setUp(self)

    def test_in_child(self):
        print 'in child'