当社では通常、ウェブサイト/ウェブアプリのエンドツーエンドのテストを作成します。つまり、URLにアクセスし、フォームに入力し、フォームを別のURLに送信して、ページの結果を確認します。これは、フォームの検証をテストしたり、HTMLテンプレートに正しいコンテキスト変数があるかどうかをテストしたりするために行います。
また、基になるロジックを間接的にテストするためにも使用します。
この理由は、エンドツーエンドのテストに合格している限り、いつでも基礎となる実装を削除して変更できるためです。
この種のデカップリングが理にかなっているのか、それともコードの小さな単位のテストを書くのを避けるための方法にすぎないのだろうか。
エンドツーエンドのテストも必要です。他にどのようにして、すべてのユニットが正しく接続されていることを知ることができますか?非常に単純なコードでは、エンドツーエンドのテストのみでコードを通るすべてのパスをテストすることができますが、レイヤーが増えるほど、そうするのに法外なコストがかかります。
たとえば、3つのレイヤーがあり、それぞれに5つの可能なパスがあるとします。アプリケーション全体のすべてのパスをテストするには、5が必要です。3 エンドツーエンドのテストですが、わずか5・3のユニットテストで各ユニットを通るすべてのパスをテストできます。エンドツーエンドのテストのみを行うと、多くのパスが無視されてしまいますが、そのほとんどはエラー処理と境界条件です。
はい、エンドツーエンドテスト(または統合テスト)は非常に理にかなっていますが、単体テストもそうです。どちらも通常は異なる種類のバグをキャッチするため、理想的には、両方が存在します。したがって、エンドツーエンドのテストは、単体テストがないことの言い訳にはなりません。
さらに数年のコーディングとプロジェクトの作業の後、私は自分の質問に対する回答を提供します。
はい、単体テストを作成する必要があります。エンドツーエンドのテストは、特にUIコンポーネントに依存している場合、作成が難しく、もろくなります。
DjangoまたはRails(または独自のカスタムクラス))のようなフレームワークを使用している場合は、フォームの検証を処理するフォームクラスが必要です。また、レンダリングされたテンプレートとフォームを表示し、GETおよびPOSTリクエストを処理するビュークラスもあります。
エンドツーエンドのテストでは、次のことを行います。
あなたはたくさんのコードをテストしていて、あなたのカバレッジはかなり良いでしょうが、すべてがうまくいった時だけハッピーパスをテストしています。フォームに正しい検証があることをどのように確認しますか?そのフォームが複数のページで使用されている場合はどうなりますか?さらに別のエンドツーエンドのテストを記述しますか?
単体テストでこれをもう一度試してみましょう:
単体テストを使用することで、より小さなコードをテストすることができ、テストは特定的で記述しやすくなります。これをTDD(テスト駆動開発)と組み合わせると、より高品質のコードが得られます。
no自動テストがあるプロジェクトでは、どこかから開始する必要があるため、単体テストの作成のしやすさは無視しないでください。単体テストから始める方が簡単で高速で、ハッピーパスだけでなく、バグのテストをすぐに開始できます。
実際には、エンドツーエンドのテスト、つまり統合テストは、完全に機能するシステムがあることを保証するため、単体テストよりも重要です。ユニットテストはシステムの統合部分をカバーしていません。これは、特に大規模なプロジェクトでは複雑なタスクです。
ただし、前述のとおり、統合テストでEdgeのケースをキャッチするのはより複雑であるため、単体テストも行う必要があります。
ユニットテストはユニットの動作を検証するのに対し、システムの動作を検証します。それぞれのメリットとコストは異なります。どちらか一方または両方を実行できます。
私の仕事では、単体テストなしで受け入れテスト駆動開発を行っています。これは、あなたが説明したものに似ています。私たちは、両方のテストを開始し、時間の経過とともに、最終的に単体テストのコストを削減して、メリットを超えました。
そうは言っても、問題のドメインと環境のコスト/メリットが、さまざまな自動テストプラクティスを含め、開発の実践に従事するための決定を促すものだと思います。私は信仰よりも、すべての実践が、それらをバックアップするために使用するという文脈の中で、経験的な証拠を持つことを好みます。