2015-11-03 109 views
5

当在测试设置中有重大的重叠时,它可以让事情继续使用继承。但是,这会造成一些问题与测试执行的不必要的重复:为什么派生类中的测试重新运行父类测试?

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 

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

我可以通过将安装程序移动到一个未发现的类,然后使用多个继承来解决此问题,但它似乎有点hacky和不必要的。在其他选手如鼻(nosetests -s example.py)和pytest(py.test example.py

+2

因为他们继承父母的测试方法,所以当'unittest'看起来通过他们的'dir'(或'__dict__'或任何它)对于开始'test_'的方法,它也找到了继承的方法。我不认为解决这个问题需要多重继承;抽象出什么都需要第三个不可检测的类,没有'test_'方法,并让它们都继承它。 – jonrsharpe

+0

内省具有包含由test前缀的方法的父类的子类将显示具有这些方法的子类。这是python OOP。我不认为将设置方法移动到mixin或者作为单独的基类看起来好像很乱,也可能是DRYer – dm03514

+0

对于不同“测试组”来说,它似乎是一个很好的用例,可以动态创建所需的确切测试。 ..tree继承在这里看起来不是正确的模型。 – Shashank

回答

3

测试亚军查找的开始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 
+0

是的,我知道这个解决方法,并在过去使用它。但我不喜欢它! – wim

+0

我已经解决了类似于此的模式 - 而不是'PotatoTestTemplate'我使用'PotatoSetup(object)'。它不是'TestCase',它更像是一个混合。然后,如果需要,我可以在任一测试中使用“PotatoTest(PotatoSetup,TestCase)'和'SpudTest(PotatoSetup,TestCase)'以及额外的设置。 – wim

1

另一个我见过人们使用的解决方法是嵌套类不会作为nosetests的一部分运行,例如,

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不会从测试用例和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

1

如果测试设置从不同的测试类是所有你需要,你可以这样做:

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'