2015-11-03 64 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' 
相關問題