これは実際には言語に依存しません。しかし、私はあなたに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つのメソッドのみ)?
理想的なケースは何ですか?
理論的な観点から、インスタンス化可能なクラスのパブリックメソッドのみをテストする必要があります(標準ではOOP言語で)必要なのは(特定のメソッドまたはクラス全体に対して)「その入力に対してどの出力を出力するか」だけなので、内部動作をテストしても意味がありません。強制するため、できる限りそれを尊重するようにしてください。クラスの encapsulation と、アーキテクチャに決定的な可能性がある提供されたインターフェイスについていくつか質問します。
実用的な観点から、実装された具象サブクラスまたは子クラスの90 +%をファクタリングする抽象クラスのないいくつかの抽象ヘルパークラスを使用できる場合がありますまた、保護されたメソッドにプラグインせずに出力をテストするのが難しい場合。このような場合、サブクラスを mock できます。
簡単な例では、クラスTiger
(およびパブリックメソッドeat
)のみをテストすることをお勧めします。
[〜#〜] tdd [〜#〜] を考えている人のためのメモです。 TDDでは、
Mammal
はリファクタリングフェーズの結果であるため、クラスTiger
の前にクラスMammal
のコーディングを開始してはなりません。したがって、Mammal
に対する特定のテストはありません。
私がこれに取り組む方法は:
Mammal
の最小限のテスト可能なサブクラスを作成します。Mammal
のパブリックメソッドを再度テストするサブクラスごとに個別の単体テストを記述しますが、そのサブクラスに固有の動作をアサートします。これにより、最小限のテストで必要なテスト範囲が得られます。
1つの代替アプローチは、サブクラスのみをテストすることです。サブクラスの単体テストの1つでも、Mammal
に固有の機能をアサートします。これにより、特定のテストサブクラスを作成する必要がなくなりますが、次の2つの欠点があります。
Mammal
を個別にテストしなくなったため、Mammal
固有のコードのテストは、サブクラスの問題が原因で失敗する可能性があります。Mammal
のプロパティがどのように、どこでテストされているかは、他の人にはわかりにくいかもしれません。テストするときは、実装の詳細ではなく、コードの外部動作に焦点を当てる必要があります。コンテキストがわからないので、ここではいくつかの大きな仮定をします。
(潜在的に抽象的な)哺乳類スーパークラスの動作に本当に関心がありますか?継承による再利用の関係は重要ですか?継承関係を構成ベースの戦略に置き換えるとしたらどうでしょうか。
私はあなたが実際に気にかけているクラスの振る舞いをテストすることに焦点を合わせます:「タイガーは期待通りに食べますか?」コードの再利用のためだけに導入されたいくつかの抽象スーパークラスをテストする代わりに。