ユニットテストが失敗する唯一の理由
ここでは、ユニットテスト、インテグレーションテスト、システムテストを考えれば十分です。ユニットテスト(とテストするために設計されたユニットに最も近いもの、たとえば、メソッド、クラス、モジュール)は、その失敗がテスト中のユニット内のコード不具合だけに原因があることを保障すべきです。
つまり、厳密に言えば、ユニットテストが失敗する唯一の理由は、コードユニットの不具合であり、ユニットが相互作用するコードの他の部分の不具合ではないのです。一方、インテグレーションテストは、より高度な抽象レベルになるように設計され、同時に相互作用する多数のユニットをテストします。最終的に、システムテストは、システム全体を部分ではなく、全システムとしてテストするように設計されます。
ユニットテストは、そのユニットをコーディングした開発者によって作成されるべきであると、今日のソフトウェア業界では一般的に了解されています。さらに、開発者のコードのメンタルモデルを正確に捉えるため、コードと同時に作成すべきだと考えられています。ユニットテストはコード作成前に作成すべきだと提案する研究もあります。
いずれにしても、このようなユニットテストは、現在そして今後のコード開発者に対して、コードユニットが意図する機能を伝えており、ある意味、コードを文書化する目的を担っています。インテグレーションテストも、実装という意味では最近ますます、相互作用する相手からユニットを遮蔽する必要がある足場コード(モック、スタブ、フェイク、シム<詰め物>など)がないことを除いて、ユニットテストと似ていますが、開発者によりテストの多くが作成されています。
一方、システムテストは、全体としてのシステム全機能、それが使用される状況、エンドユーザがフィールドで実行させるフロー/シナリオ、それが用いるハードウェアプラットフォームの構成を詳しく理解している「テスター」により相変わらずその大部分が作成されています。システムテスターは、顧客と要件定義エンジニアと協力し合い、システムの最終的な使用方法をよく理解しています。従って、彼らは、さしあたりシステムテストを作成するためには本当に最適な人たちです。
ユニットテストとインテグレーションテストは、例えばJunitのような開発とテストが十分進んだ自動化フレームワークを用いて現在コード化されているように、ソフトウェア開発全体工程の中でどう使用するかという点では万能です。最近のソフトウェア開発工程は、例えばgitでhookとして実現されているマルチステージチェック(multi-stage check)で表現されます。
一般的に、各ステージは、(1) コードレポジトリの前のチェックアウトを使って pre-submitモードで(ローカルマシン上で) テスト、(2) 最新のコードレポジトリを使ってpre-submitモードで (おそらく、ローカルマシンまたはクラウド上で)テスト、(3) コード変更をレポジトリーにサブミット、(4) コードレポジトリの最新スナップショットを使ってpost-submitモードでテスト、そして(5)各CIサイクルでテストです。 ユニットテストとインテグレーションテストはこれらのステージで役割を果たします。