与えられたソフトウェアが...
- システムはいくつかのサブシステムで構成されています
- 各サブシステムはいくつかのコンポーネントで構成されています
- 各コンポーネントは多くのクラスを使用して実装されています
... 各サブシステムまたはコンポーネントの自動テストを作成するのが好きです。
コンポーネントの各内部クラスのテストは作成しません (各クラスがコンポーネントのパブリック機能に貢献し、コンポーネントのパブリック API を介して外部からテスト可能/テストされる場合を除きます)。
コンポーネントの実装をリファクタリングするとき (新しい機能を追加する一環としてよく行う)、既存の自動テストを変更する必要はありません。テストはコンポーネントのパブリック API とパブリック API のみに依存するためです。通常、変更ではなく拡張されます。
このポリシーは、 Refactoring Test Codeのようなドキュメントとは対照的だと思います...
- 「...単体テスト...」
- 「...システム内のすべてのクラスのテストクラス...」
- 「... テスト コードと製品コードの比率は ... 理想的には 1:1 の比率に近づくと考えられています ...」
... 私はそのすべてに同意しないと思います (または、少なくとも練習していません)。
私の質問は、私のポリシーに同意しない場合、その理由を説明していただけますか? この程度のテストでは不十分なシナリオはどれですか?
要約すれば:
- パブリック インターフェイスはテスト (および再テスト) され、変更されることはほとんどありません (追加されることはありますが、変更されることはほとんどありません)。
- 内部 API は公開 API の背後に隠され、公開 API をテストするテスト ケースを書き直すことなく変更できます。
脚注: 私の「テスト ケース」の一部は、実際にはデータとして実装されています。たとえば、UI のテスト ケースは、さまざまなユーザー入力とそれに対応する予想されるシステム出力を含むデータ ファイルで構成されます。システムのテストとは、各データ ファイルを読み取り、システムへの入力を再生し、対応する期待される出力が得られることをアサートするテスト コードを用意することを意味します。
テスト コードを変更する必要はほとんどありませんが (通常、パブリック API は変更ではなく追加されるため)、既存のデータ ファイルを変更する必要がある場合があります (週に 2 回など)。これは、システム出力をより良いものに変更した場合 (つまり、新しい機能によって既存の出力が改善された場合) に発生する可能性があり、既存のテストが「失敗」する可能性があります (テスト コードは、出力が変更されていないことをアサートしようとするだけであるため)。これらのケースを処理するために、次のことを行います。
- 出力をアサートするのではなく、新しい出力を新しいディレクトリにキャプチャするように指示する、特別なランタイム フラグが設定された自動テスト スイートを再実行します。
- ビジュアル差分ツールを使用して、どの出力データ ファイル (つまり、どのテスト ケース) が変更されたかを確認し、これらの変更が適切であり、新しい機能が期待どおりであることを確認します。
- 新しい出力ファイルを新しいディレクトリからテスト ケースの実行元のディレクトリにコピーして、既存のテストを更新します (古いテストを上書きします)。
脚注: 「コンポーネント」とは、「1 つの DLL」または「1 つのアセンブリ」のようなものを意味します... アーキテクチャまたはシステムの配置図に表示されるのに十分な大きさのもので、多くの場合、数十または 100 のクラスを使用して実装されます。約1つまたは少数のインターフェースのみで構成されるパブリックAPIを使用...開発者の1つのチームに割り当てられる可能性があるもの(別のコンポーネントが別のチームに割り当てられる場合)、したがって、コンウェイの法則に従って比較的安定したパブリック API。
脚注: 記事Object-Oriented Testing: Myth and Realityは次のように述べています。
通説: ブラック ボックス テストで十分です。 クラス インターフェイスまたは仕様を使用して慎重にテスト ケースを設計すれば、クラスが完全に実行されたことを確認できます。ホワイトボックス テスト (テストを設計するためのメソッドの実装を見る) は、カプセル化の概念そのものに違反しています。
現実: OO 構造が重要、パート II。多くの調査によると、開発者が耐え難いほど完全であると考えているブラックボックス テスト スイートは、テスト対象の実装のステートメント (パスや状態は言うまでもなく) の 3 分の 1 から半分しか実行しないことが示されています。これには 3 つの理由があります。まず、選択された入力または状態は通常、通常のパスを実行しますが、可能なすべてのパス/状態を強制するわけではありません。第二に、ブラックボックステストだけでは驚きを明らかにすることはできません。テスト対象のシステムの指定されたすべての動作をテストしたとします。不特定の動作がないことを確認するには、システムの一部がブラックボックス テスト スイートによって実行されていないかどうかを知る必要があります。この情報を取得できる唯一の方法は、コード インストルメンテーションです。三番、
ホワイトボックスの機能テストを行っていることを付け加えておきます。コード (実装内) を確認し、機能テスト (パブリック API を駆動する) を作成して、さまざまなコード ブランチ (機能の実装の詳細) を実行します。