この質問をするために、私はそれを読んでいる全員が同じページにいることを確実にするためにいくつかの用語を定義する必要があります:
テストピラミッドの観点から、70%のユニットから20%の統合から10%の機能テストまでを統合する必要があります。
上記のように私の質問は次のとおりです:ユニットテストの大規模なスイートがある環境で作業しましたが、統合テストが不十分であるか、機能テストが存在しないため、実行時にバグがまだ表面化しています。特定のクラスの優れたユニットカバレッジがあっても、そのクラスの実際の使用方法/システムの他の部分への配線方法には、通常、ユニットレベルで実際に把握できるよりも多くのバグが含まれています。通常、これらのバグは統合/機能テストレベルで検出されます。
ユニットテストを許可すると、システムをより多くの状態に置くことができ、実行速度が大幅に向上しますが、バグ検出機能として、実際にコードパスを駆動する統合/機能レベルのテストと比較して低下します。他の人とこのポイントを上げると、通常の応答は「ああ、統合テストは実際には作成していない単体テストを見つけている!」と言うことです。これは一見有効なようですが、コードをテストしているだけです2回:完全なカバレッジでの統合レベルで1回と、カバレッジのレベルを保証できないユニットレベルで1回。ただし、両方のセットを維持する必要があります。
私の質問は、統合テストのセットアップが最小限に抑えられているか、共通のテストセットアップライブラリで抽象化されている場合、統合テストを単体テストの「最初の行」として使用しないのはなぜですか?すべてを2回テストすることの実際の価値は何ですか?
これはAです。2回クリックした後、カウントAに尋ねると、Aは2を与えます。 Aがこのように機能することを知っているのは、それを実行するコードを見て、それが実行されるのを見たからです。中を見なくてもAがどうあるべきかを理解しているように感じます。
これがシステムabcxyzです。起動すると、走行距離計(またはスコアボード、または数字の表示)のようなGIFが生成されます。多くのワイルドで素晴らしい方法で構成できます。しかし、それを実行する統合テストコードを見てみると、まあ...何を期待しているのか、何がカウントされているのか、どこでこれらのイメージを取得しているのかを理解するには、少し時間がかかります。あなたはこれが何であるかを知っていると思いますが、変更を加えるときは、abcxyzを何が使用しているかを理解する必要があることに気づきました。したがって、システムの残りの部分を確認します。あなたは読み続けます...そして読みます...ため息...
私は両方のテストを受けるのが好きです。ユニットテストが、筆者がAにとって本当に重要だと思ったことを理解しているという自信が好きです。クラス定義よりも、よくできた単体テストの方が読みやすいと思います。
私は向きを変えて、統合テストについての私の理解を知らせるためにそれを使いたいです。単体テストなしでこれを行うと、ブレンダーに入れてから4コースのディナーを食べるような気分になります。できます。しかし、残念。
そして、それはコードを読むことのようなものです。
読みやすいコードの記述方法について、コードの記述が簡単になるようなことは決して信用しないでください。
これは、トップダウン開発とボトムアップ開発の問題です。大きなマシンを構築する場合、最初にシステム全体を構築してからそれを全体としてテストしますか、それとも全体を組み立てる前に各コンポーネントを個別に開発してテストしますか?正解は、両方を実行することです。確かにシステム全体をテストする必要がありますが、コンポーネントを個別にテストすることには多くの利点もあります。
テストの詳細レベルを上げることの利点は、問題の存在だけでなく、正確な問題を特定できることです。
また、要件のテストと、単体テストを行うシステムの個々の部分の要件の定義についても検討する必要があります。
たとえば、オファーやモノに基づいて製品のバスケットの価格を返すBasketPriceCalculatorがあるとします。 2対1のオファーの単体テストを行って失敗した場合、そのクラスのオファーに問題があることがわかります。チェーン内のいずれかのコンポーネントが失敗した場合、同等の統合または機能テストが失敗する可能性があるのに対し、.
また、バスケットに7個を超えるアイテムがある場合、BasketPriceCalculatorがエラーをスローするという特定の要件があるかもしれません。エラーを処理し、他のアクションを実行する可能性がある製品全体ではなく、コンポーネントに固有であるため、依存関係を含めずにその要件をテストしたいと思います。
全体的に私はあなたに同意します。統合テストはユニットテストよりも重要であり、モックモックと実際の依存関係を使用してすべてのユニットテストを実行してはならない理由は実際にはありません。データ駆動テストでこれを行います。
機能テストはさらに重要であり、実行速度が遅くても、機能テストと見なすことができるすべてのシナリオを実行しない理由は実際にはありません。結局のところ、ユーザーはそうするでしょう。
しかし、実際には、ゼロから何かを開発する場合、機能テストを記述できる機能するアプリから始める必要はありません。与えられたいくつかのルールに基づいてバスケットの価格を計算する小さなコンポーネントから始めます。したがって、最初にそのビットの単体テストを記述します。