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

Why do tests in derived classes rerun the parent class tests?

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

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

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

我可以通过将设置移动到未发现的 class 来解决这个问题,然后使用多重继承,但这似乎有点老套和不必要。

注意:同样的问题出现在其他跑者如nose(nosetests -s example.py)和pytest(py.test example.py)

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

from unittest import TestCase

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

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

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

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

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 class 扩展了对象,而 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

如果您只需要来自不同测试 class 的测试设置,您可以这样做:

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'