web-dev-qa-db-ja.com

プライベート/保護されたメソッドを単体テストする必要がありますか

これは実際には言語に依存しません。しかし、私はあなたにpythonでコンテキストを与えます。

この親クラスがあります

class Mammal(object):
    def __init__(self):
        """ do some work """

    def eat(self, food):
        """Eat the food"""
        way_to_eat = self._eating_method()
        self._consume(food)

    def _eating_method(self):
        """Template method"""

    def _consume(self, food):
        """Template method"""

ここでeatは唯一のパブリックメソッドですが、_consumeおよび_eating_methodは実際には保護されたメソッドであり、子クラスによって実装されます。

Mammalクラスのみを記述した場合、何をテストしますか?

明らかに4つの方法すべて。

さあ、子供を紹介しましょう

class Tiger(Mammal):    
    def _eating_method(self):
        """Template method"""

    def _consume(self, food):
        """Template method"""

このクラスを見てください。 2つprotectedメソッドしかありません。

Tiger(継承された2つを含む)の4つのメソッドすべてをテストするか、導入された変更をテストするだけですか(オーバーライドされた2つのメソッドのみ)?

理想的なケースは何ですか?

21
Shiplu Mokaddim

理論的な観点から、インスタンス化可能なクラスのパブリックメソッドのみをテストする必要があります(標準ではOOP言語で)必要なのは(特定のメソッドまたはクラス全体に対して)「その入力に対してどの出力を出力するか」だけなので、内部動作をテストしても意味がありません。強制するため、できる限りそれを尊重するようにしてください。クラスの encapsulation と、アーキテクチャに決定的な可能性がある提供されたインターフェイスについていくつか質問します。

実用的な観点から、実装された具象サブクラスまたは子クラスの90 +%をファクタリングする抽象クラスのないいくつかの抽象ヘルパークラスを使用できる場合がありますまた、保護されたメソッドにプラグインせずに出力をテストするのが難しい場合。このような場合、サブクラスを mock できます。

簡単な例では、クラスTiger(およびパブリックメソッドeat)のみをテストすることをお勧めします。

[〜#〜] tdd [〜#〜] を考えている人のためのメモです。 TDDでは、Mammalはリファクタリングフェーズの結果であるため、クラスTigerの前にクラスMammalのコーディングを開始してはなりません。したがって、Mammalに対する特定のテストはありません。

36
Gnucki

私がこれに取り組む方法は:

  • パブリックメソッドの動作を単体テストできる2つの保護されたメソッドの最小限の実装を提供するMammalの最小限のテスト可能なサブクラスを作成します。
  • Mammalのパブリックメソッドを再度テストするサブクラスごとに個別の単体テストを記述しますが、そのサブクラスに固有の動作をアサートします。

これにより、最小限のテストで必要なテスト範囲が得られます。

1つの代替アプローチは、サブクラスのみをテストすることです。サブクラスの単体テストの1つでも、Mammalに固有の機能をアサートします。これにより、特定のテストサブクラスを作成する必要がなくなりますが、次の2つの欠点があります。

  • Mammalを個別にテストしなくなったため、Mammal固有のコードのテストは、サブクラスの問題が原因で失敗する可能性があります。
  • Mammalのプロパティがどのように、どこでテストされているかは、他の人にはわかりにくいかもしれません。
5
robjohncox

テストするときは、実装の詳細ではなく、コードの外部動作に焦点を当てる必要があります。コンテキストがわからないので、ここではいくつかの大きな仮定をします。

(潜在的に抽象的な)哺乳類スーパークラスの動作に本当に関心がありますか?継承による再利用の関係は重要ですか?継承関係を構成ベースの戦略に置き換えるとしたらどうでしょうか。

私はあなたが実際に気にかけているクラスの振る舞いをテストすることに焦点を合わせます:「タイガーは期待通りに食べますか?」コードの再利用のためだけに導入されたいくつかの抽象スーパークラスをテストする代わりに。

0
prgmtc