web-dev-qa-db-ja.com

テストクラスの継承

インターフェイスSerializerとメソッドserializeisSerializerForがあります。私はTDDを使用してこれの最初の実装を作成し、Niceクリーン実装を完全にカバーするNiceクリーンテストケースで終わりました。より具体的なアイデアを得るために、ここに 1つの関連するコミット を示します。

ここで、他の誰か(TDDに慣れていない人)が、このSerializerインターフェースの2番目の実装の作成を開始しました。この人は、2番目の実装に必要なテストが私の最初のテストとある程度重複するだろうと考えました。そのため、すべてのシリアライザテストケースに共通していると思われるメソッドを保持する シリアライザテストの抽象基本クラス が作成されました。

これには2つの主な理由で満足できません。まず、ここで継承が使用される唯一の理由は、コードの再利用のためです。これは大きなコードの匂いです。第二に、これはTDDサイクルを壊します。 Serializerの別の実装を作成し、基本テストクラスの派生物を作成したい場合、すべての製品コードを1つのステップで実装する必要があります。

一方、テストクラスの共通コードを単純に複製することも、かなり奇妙に思えます。ここでは、これらの問題を回避するために、正しい方法でコンポジションを使用できることを願っています。

これはかなり一般的な状況のようです。これをどのように解決しますか?どのように違うと思いますか?

6
Jeroen De Dauw

まず、ここで継承が使用される唯一の理由は、コードの再利用のためです。これは大きなコードの匂いです。

異なるシリアライザー実装(SerializerASerializerBSerializerCなど)は、異なるSerializerTestクラス(SerializerTestASerializerTestBSerializerTestC)につながります。これらはすべて「シリアライザーテスター」であり、共通のSerializerTester基本クラスへの「is-a」関係を提供するため、継承おそらくここで正しいツールです。

Serializerの別の実装を作成し、基本テストクラスの派生物を作成したい場合、すべての製品コードを1つのステップで実装する必要があります。

私はそうは思いません。テストクラスSerializerTestAを作成してTDDを開始します(SerializerTesterオブジェクトを作成するだけでSerializerAから派生します。これはコンパイルされません。テストはREDです。次にSerializerAを実装するのは、Serializerのコンストラクターと空のメソッド実装だけです。インターフェース-テストは緑です。次に、最初のテストメソッドをSerializerTestAに追加します。これにより、テストコールがSerializerTesterの対応するメソッドに委任される場合があります。SerializerAの実装がないため、テストは失敗します-再度赤SerializerAの最初の空のメソッド。最初のメソッドが失敗するまで、テストステータスは再び緑になります。

したがって、SerializerTesterクラスの完全な実装を必要とするSerializerからテストメソッドを呼び出さない限り、従来のTDDパスを維持したまま、段階的にこれを行うことができます。

6
Doc Brown