2015-11-03 8 views
5

テストセットアップに重大な重複がある場合、継承を使用するように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 

なぜですか?これは設計によるものですか?テストランナーを特定の方法で設定することで無効にすることはできますか?

セットアップを未検出のクラスに移動し、複数の継承を使用して問題を回避することはできますが、ハッキーで不必要なようです。

注:同じ問題は、このような鼻(nosetests -s example.py)とpytest(py.test example.py

+2

をまたは何でもそれがありません) 'test_'を開始するメソッドに対しては継承されたものも見つけます。私はこれを解決するには*複数の継承が必要だとは思わない。 'test_'メソッドを持たない、発見できない第3のクラスに必要なものを抽象化し、両方を継承させます。 – jonrsharpe

+0

testで接頭辞付きのメソッドを含む親クラスを持つサブクラスを調べると、それらのメソッドでサブクラスが表示されます。これはPythonのOOPです。私はセットアップ方法をミックスインまたは別のベースクラスとして動かすことはまったく問題ないと思っています。おそらくDRYerです – dm03514

+0

必要な正確なテストをダイナミックに作成するテストの異なる "グループ"のミックスインの素晴らしいユースケースのようです。 ..tree-inheritanceはここで正しいモデルのようには見えません。 – 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(オブジェクト)'を使います。これは 'TestCase'ではなく、mixinのようなものです。次に、必要に応じて、いずれかのテストで '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' 

Iが失敗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

を使用してのように見えます別のテストクラスはあなたが必要とするすべては、あなたがこれを行う可能性がある:彼らは両親のテストメソッドを継承するため、 `unittest`が自分の` dir`を通して見るとき、または `__dict__`(そう、

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' 
関連する問題