web-dev-qa-db-ja.com

すでに統合テストを行っている場合、単体テストは必要ですか?

私のプログラムの統合テストがすでにあり、それらすべてが合格した場合、うまくいくと感じています。次に、単体テストを作成/追加する理由は何ですか?とにかくすでに統合テストを作成する必要があるので、統合テストでカバーされていないパーツの単体テストのみを作成します。

統合テストに対する単体テストの利点は

  • 小さくて高速に実行できる(ただし、新しいユニットを追加して何かをテストすることは、統合テストですでにテストされているため、テストスーツ全体が大きくなり、実行時間が長くなります)
  • 1つのことだけをテストするため、バグを見つけやすくなります(ただし、統合テストが失敗したときに、単体テストの書き込みを開始して、個々のパーツを検証できます)
  • 統合テストで検出されない可能性のあるバグを見つけます。例えばバグのマスキング/オフセット。 (ただし、私の統合テストがすべて成功した場合、つまり、いくつかの隠れたバグが存在してもプログラムが機能することを意味します。これらのバグを見つけて修正することは、将来の統合テストを壊したり、パフォーマンスの問題を引き起こしたりしない限り、それほど優先度が高くありません)

そして、私たちは常に少ないコードを書きたいと思っていますが、ユニットテストを書くにはもっと多くのコードが必要です(主にモックオブジェクトをセットアップします)。いくつかの単体テストと統合テストの違いは、単体テストではモックオブジェクトを使用し、統合テストでは実際のオブジェクトを使用することです。これは多くの重複があり、コードの動作を変更するためのオーバーヘッドが追加されるため、テストでも重複したコードが好きではありません(リファクタリングツールは常にすべての作業を実行できるわけではありません)。

48
Bryan Chen

ユニットテストに対する賛成論と反対論を提示しました。 "正の引数の値が負の値のコストを上回るかわかりますか?" =私は確かにそうします:

  • 小型で高速はユニットテストの優れた側面ですが、決して最も重要ではありません。
  • バグを見つけるのが簡単なのは非常に価値があります。専門的なソフトウェア開発に関する多くの研究は、バグが古くなり、ソフトウェア配信パイプラインを下っていくにつれて、バグのコストが急激に上昇することを示しています。
  • マスクされたバグを見つけることは価値があります。特定のコンポーネントの動作がすべて検証されていることがわかっている場合は、これまで使用されていなかった方法で、自信を持って使用できます。唯一の検証が統合テストによる場合、そのcurrentの使用が正しく動作することだけがわかります。
  • モックは実際のケースではコストがかかり、モックを維持することは二重にコストがかかります。実際、「興味深い」オブジェクトまたはインターフェースをモックする場合、モックオブジェクトが実際のオブジェクトを正しくモデル化していることを確認するテストが必要になることもあります。

私の本では、長所は短所を上回っています。

33
Ross Patterson

既存の統合テストケースをユニットテストとして再実装することにはあまり価値がありません。

多くの場合、統合テストはtdd以外のレガシーアプリケーション用に作成する方がはるかに簡単です。通常、テスト対象の機能は密結合されているため、単体でのテスト(=単体テスト)は困難/高価/不可能です。

> Then what are the reasons to write/add unit tests?

私の意見では、ユニットテストbeforeを実際のコードで記述した場合、テスト駆動開発が最も効果的です。このようにして、テストを実行するコードは、簡単にテストできる最小限の外部参照で明確に分離されます。

ユニットテストなしでコードが既に存在する場合、コードは簡単なテスト用に作成されていないため、通常、後でユニットテストを作成するのは多くの追加作業になります。

TDDを実行すると、コードを自動的に簡単にテストできます。

8
k3b

統合テストでは、複数のコンポーネントが期待どおりに連携していることのみを確認する必要があります。個々のコンポーネントのロジックが正確かどうかは、単体テストで検証する必要があります。
ほとんどのメソッドにはいくつかの可能な実行パスがあります。 if-then-elseや、予期しない値や単なる間違った値を持つ入力変数などを考えてみてください。通常、開発者はハッピーパス(間違っていない通常のパス)についてのみ考える傾向があります。ただし、他のパスに関する限り、2つのオプションがあります。エンドユーザーがUIで実行するアクションを通じてこれらのパスを探索し、アプリケーションがクラッシュしないことを期待するか、アサートするユニットテストを作成できます。これらの他のパスの動作と必要に応じてアクションを実行します。

5
Stefan Billiet

あなたがあなたの質問で指摘した理由のいくつかは本当に重要であり、それ自体で単体テストを支持することで非常によく主張することができますが、YMMV。たとえば、統合テストスイートをどのくらいの頻度で実行しますか?統合テストでの私の経験は、遅かれ早かれ遅くなるので、変更を加えるたびに実行されず、バグを挿入してから検出するまでの時間が長くなるということです。

また、あなたがしている大きな間違いはそれを信頼することです

Find bug that may not be caught in integration test. e.g. masking/offsetting bugs.

重要ではありません。ユーザーがバグを見つけることを期待していますか?統合テストから得られたカバレッジを信頼することは私の考えでは危険です。非常に簡単にカバレッジの%を取得できますが、実際にはほとんどテストしていません。

統合テストに対する標準的な参照はJBrainsの投稿だと思います。

http://www.jbrains.ca/permalink/integrated-tests-are-a-scam-part-1

まだ読んでいない場合に備えて。

最後に、IMOは、設計の単体テストから得られるフィードバックが非常に貴重です。直感でデザインを判断し、統合テストに依存することも間違いかもしれません。

4
José Ricardo

コードを変更またはリファクタリングする必要があると予想される場合は、単体テストが不可欠です。ユニットテストは、コードが記述された時点でバグを実証するためだけでなく、コードがさらに記述されたときに新しいバグがいつ現れるかを示すために存在します。

はい、最初に統合テストと単体テストを作成する方がはるかに優れていますが、後で作成する場合でも、それらを使用することには多くの価値があります。

1
Matthew Flynn