すでに統合テストがある場合、ユニットテストが必要ですか?


47

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

統合テストよりも単体テストの利点を知っているのは

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

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


好奇心から、あなたの統合テストはどれくらいの範囲をカバーしていますか?また、複雑なロジックがある場合、統合テストはそれらのすべてまたは一部のみをカバーし、ビジネスまたはランダムに重要な部分をカバーしますか?
シバン

この質問はあいまいに思えます。インタラクターgithub.com/collectiveidea/interactor)を呼び出すRailsコントローラーメソッドがあるとします。コントローラーメソッドの統合テストを作成することにしました(それらがないと、APIエンドポイントが機能することを信頼できません)。ここには少なくとも2つの質問があります。(1)コントローラーメソッドの単体テストも作成する必要があります(つまり、統合テストと同じ動作をテストする単体テストを作成する必要があります)。私のインタラクターのために?特定のビジネスコンテキストでは、これら2つの質問に別々に答えます。
ダニエル

回答:


33

ユニットテストの賛否両論について説明しました。ですから、否定的な議論のコストを上回る肯定的な議論の価値を見ますか? と自問する必要があります。

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

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


2
現実世界の場合、安く m笑していませんか?モックが受信するメッセージに対する期待を設定し、モックが返すものを指定するだけです。
ドッグウェザー14

10
@Dogweather Mocksは最初に作成されたときにうまく機能します。時間の経過とともに実際のオブジェクトが変更されると、モックもそれに合わせて変更する必要があります。10年と6,000回のユニットテストが行​​われているため、「成功した」テストが本当に成功したことを知るのは非常に困難です。
ロスパターソン14

1
余談ですが、その「10年と6,000ユニットテスト」は誇張ではなく、個人的な経験からの数字です。
ロスパターソン

3
2004年または2005年に自動化された開発者テスト(ユニットと統合、ただしほとんど後者)の記述を開始し、Java用の高度なモックライブラリを開発しました。私は(DBの変更、またはネットワークの変更など)同じ理由で破り、複数の統合テストを見て、私は時々 、再利用可能なコンポーネントのための「低レベル」の統合テストを書くが、それでも、私は多くのことを好む多くの回のみ持っています統合テスト。ほとんどの場合、モックを使用した単体テストは価値がありません。統合テストの補助としてのみ、モックを適用します。
ロジェリオ

最後の箇条書きは、あなたが行っている議論と矛盾しているようです。この箇条書きでは、不要なモッ​​クの作成を禁止しています。これは、すでに統合テストでカバーされているパーツの単体テストを作成することに対する議論です。ただし、議論の目的は、統合テストですでにカバーされているパーツの単体テストを作成することです。ここで@RossPattersonの意図を明確にしてください。
ダニエル

8

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

統合テストは、通常、テスト対象の機能が密結合されているため、非tddレガシアプリケーションの記述がはるかに簡単になります。

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

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

コードが単体テストなしで既に存在する場合、通常は簡単なテストのためにコードが記述されていないため、単体テストを後で記述するのは多くの余分な作業です。

TDDを行うと、コードは簡単にテストできます。


2
noのレガシアプリケーションがありunit-testsunit-tests特定の部分に含める場合integration tests、レガシコード用に最初に記述する方が良いと思いますか。それが書かれたら、密結合を解き、テストできるインターフェースで関数を作成できますか?integration-testすでに作成されているので、リファクタリングの各ステップで、コードの新しいバージョンが希望どおりに機能することを確認できますか?
alpha_989

2
@ alpha_989、これは非常に私見であり、私は他のアイデアを聞いてもかまいませんが、レガシーコードの単体テストよりも統合テストを好むでしょう。いずれの場合も、何らかのテストを追加する前にメソッドが正しく機能していることを確認する必要がありますが、統合テストでは、個々のコード要素ではなくメソッドの全体的な期待が機能していることを確認します。
ブリットウェスコット

5

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


4

あなたがあなたの質問で指摘した理由のいくつかは本当に重要であり、それだけで単体テストを支持する可能性がありますが、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

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

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


私は本当にその記事を受け取りません。だから、コードパスがたくさんあり、統合テストではそれらをすべてカバーすることはできません...そうですか?ユニットが無意味であるほど些細でない限り、ユニットテストにも同じことが当てはまります。
ケーシー

これは、コードカバレッジを固定することに対する議論のようなものであり、大量の単体テストを作成して統合テストを回避する必要があるということです。
ケーシー

1

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

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


3
あなたが主張したとは思わない。統合テストではコードのバグも明らかになり、実際には単体テストでは検出できないバグをキャッチできます。
ケーシー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.