現在、TDDと単体テストが大きな絶賛のようです。しかし、それは他の形式の自動テストと比較して本当に便利ですか?
直感的には、自動化された統合テストは単体テストよりもはるかに有用だと思います。私の経験では、ほとんどのバグはモジュール間の相互作用にあるようであり、各ユニットの実際の(通常は制限された)ロジックではありません。また、モジュール間のインターフェースの変更(および事前条件と事後条件の変更)が原因で、しばしばリグレッションが発生しました。
私は何かを誤解していますか、または統合テストと比較してユニットテストがそれほど注目されているのはなぜですか?それは単に、統合テストがあなたが持っているものであると想定されているためであり、ユニットテストは開発者として適用するために学ぶ必要がある次のことですか?
あるいは、単体テストでは、自動化の複雑さと比較して、最も高い利益が得られるだけでしょうか?
自動化された単体テスト、自動化された統合テスト、および自動化された受け入れテストでどのような経験をしましたか?また、あなたの経験で最も高いROIをもたらしたものは何ですか?なぜですか?
次のプロジェクトで自動化するテストの形式を1つだけ選択する必要がある場合、どれを選択しますか?
前もって感謝します。
単体テストを非常に有用にする1つの重要な要素は高速フィードバックです。
アプリが統合/システム/機能テストで完全にカバーされている場合に何が起こるかを検討します(これは、ほとんどの開発ショップで現実から遠く離れている理想的な状況です)。これらは多くの場合、専用のテストチームによって実行されます。
これにはすべて数日から数週間かかる場合があります。この時点で、すでに他のタスクに取り組んでいるので、先に書かれたコードの詳細は思い浮かびません。さらに、通常、バグが実際にどこにあるのかを直接証明することさえないため、バグを見つけて修正するにはかなりの時間がかかります。
一方、単体テスト(TDD)では
これはすべて分の問題で発生します。
これは、統合/システムテストが役に立たないと言っているのではありません。それらは単に異なる目的を果たします。適切に記述された単体テストを使用すると、コード内のバグの大部分をキャッチできますbefore統合フェーズに到達します。統合フェーズでは、バグを見つけて修正するのがすでにかなり高くつきます。統合テストは、単体テストでは検出が困難または不可能な種類のバグを検出するために必要です。しかし、私の経験では、これらはまれな種類です。私が見たほとんどのバグは、メソッド内のどこかで単純な、または些細な省略が原因で発生します。
言うまでもありませんが、単体テストではインターフェイスの使いやすさや安全性などもテストされるため、デザインやAPIを改善するために非常に重要なフィードバックが得られます。モジュール/サブシステム統合のバグの可能性を大幅に減らすことができるIMHOはどれですか。APIが簡単でクリーンなほど、誤解や脱落の可能性が低くなります。
自動化された単体テスト、自動化された統合テスト、および自動化された受け入れテストについてどのような経験がありますか。また、経験上、最高のROIをもたらしたものは何ですか。なぜ?
ROIは多くの要因に依存しますが、おそらく一番の要因は、プロジェクトがグリーンフィールドかレガシーかです。グリーンフィールド開発での私のアドバイス(およびこれまでの経験)は、最初からTDDスタイルのユニットテストを行うことです。この場合、これが最も費用効果の高い方法であると確信しています。
ただし、レガシープロジェクトでは、十分なユニットテストカバレッジを構築することは巨大の取り組みであり、利益を得るには非常に時間がかかります。可能であれば、UIを介してシステム/機能テストで最も重要な機能をカバーすることを試みるのがより効率的です。 (デスクトップのGUIアプリは、GUIを介して自動的にテストすることが難しい場合がありますが、自動テストサポートツールは徐々に改善されています...)。これにより、粗いが効果的なセーフティネットが迅速に得られます。その後、アプリの最も重要な部分を中心にユニットテストを徐々に構築していきます。
次のプロジェクトで自動化するテストの形式を1つだけ選択する必要がある場合、それはどれですか。
それは理論的な質問であり、私には無意味だと思います。あらゆる種類のテストが優れたソフトウェアエンジニアのツールボックスで使用されており、これらすべてのテストにはかけがえのないシナリオがあります。
すべてのタイプのテストは非常に重要であり、システムのさまざまな側面が仕様に適合していることを確認します。逆に言えば、「1つのタイプのテストを選択しなければならない場合...」とは思いませんでした。単体テストは、統合テストや人によるインタラクティブテストとは異なるフィードバックを提供します。
テストの種類/利点は次のとおりです。
オプションですが推奨されるテスト:
ユニットテストが統合テストよりも優れている理由を理解するには、包括的である必要がある追加のテストの桁数を理解する必要があります。ユニットAのすべての可能な結果について、テストが必要です。ユニットBについても同じです。これらの両方が連携してより完全なソリューションを実現する場合、テストの数は組み合わせになります。つまり、ユニットAとユニットB間の相互作用のすべての順列をテストするには、A * Bテストが必要です。ユニットCを追加すると、トリオのテスト数はA * B * Cになります。
ここで、インターフェースとオブジェクト境界の概念が非常に重要になります。インターフェイスは特定の契約を表します。インターフェイスのimplementorは、特定の方法で動作することに同意します。同様に、インターフェイスのconsumerは、特定の方法で実装を使用することに同意します。インターフェイスを実装するすべてのクラスを収集するテストを作成することにより、各実装がインターフェイスコントラクトを監視することを簡単にテストできます。それは方程式の半分です。残りの半分は、コンシューマ側をテストすることです。これは、模擬オブジェクトが入ってくる場所です。モックは、相互作用が常に仕様どおりになるように構成されています。この時点で必要なのは、実装者/消費者の契約が正しいことを確認するためのいくつかの統合テストです。
これらは、さまざまな目的を持つさまざまなツールです。
単体テストは設計ツール(TDD)であり、リファクタリングのほとんどの前提条件です。
統合テストは、プロジェクトの進行状況を視覚化するのに最適であり、回帰バグを回避するのにも最適です。
覚えておくべきポイントは、統合テストを使用して実際に設計することはできず、単体テストでは回帰を検出できないことです。
私は Selenium をサニティチェックに幅広く使用しました。
大規模なWebパブリッシング会社では、新しいリリースが作成されたとき、テストスクリプトごとに、通常3人のテスターが1〜2時間ですべてのサイトファミリーにアクセスし、すべてが問題ないことを確認しました。 Seleniumを使用して、テストを自動化し、複数のマシンとブラウザーに配布することができました。現在、テストスクリプトを実行すると、3台のPCが同じことを自動的に実行してかなりのレポートを出力するのに約10分かかります。
Seleniumの優れた点は、XUnit、TestNG、MSTestなどの単体テストフレームワークと連携できることです。
私の経験では、それは非常に貴重でしたが、そのような設定は実際にはプロジェクトとチームに依存するため、ROIは確実に異なります。
最良のROIは通常、そのタイプのバグを見つけることができる最も早いテストです。
単体テストでは、1つのメソッドまたは1つのコンポーネントにあるほとんどのバグを検出する必要があります。通常は数分で修正できるバグを発見し、総所要時間は1時間未満です。非常に安価なテスト、見つけて修正する非常に安価なバグ!これらのバグが統合テストに組み込まれた場合、そのバグが別のバグによって塞がれていないと仮定すると、ターンアラウンドは1日(テストの実行はしばしば毎晩行われる)のようになります。さらに、他のコードが最初のバグのあるコードに対して作成されたため、さらに多くのバグが導入される可能性があります。さらに、再設計は、より多くのコードに影響を与えます。また、統合テストを完了する前に、より多くのバグを許容するためには、さらに多くのテストを実行する必要があります。不十分な単体テストは、長くて面倒な高価テスト統合サイクルの中心にあることがよくあります。単体テストをスキップすると開発時間が半減する可能性がありますが、テストには少なくとも3〜4倍の時間がかかり、プロジェクト全体の長さが2倍になり、IMEを単体テストした場合よりも品質が低下します。
統合テストは、通常、統合バグを見つけることができる最も早い実際のテストです(ただし、レビュープロセスでは、ソフトウェアが作成される前、またはコードがテストされる前に、いくつかのバグを見つけることができます)。ソフトウェアをユーザーまたはリリースに表示する前にこれらのバグを見つけたいと考えています。バグを最後に修正する(またはホットフィックスする!)には非常にコストがかかるためです。統合するために複数の機能するコンポーネントが(定義により)必要なため、それらのバグを早期に見つけることができません。より興味深いテストを開始する前に、相互作用する部分(マイナーなタイプミスなど)とは関係のないバグを最初に解決する必要がある場合、統合テストの速度が低下します。
ユーザー受け入れテストは、ソフトウェアが顧客の望むことを確実にします(顧客はプロジェクト全体の終わりに期待と実際のソフトウェアの間に大きなギャップを見つけるリスクを減らすためにずっと関与していたと思いますが)-非常に高価です!)。テストのこの段階に到達するまでに、少なくとも仕様と比較して、製品のほとんどのバグがすでに発見されていると本当に信じるべきです。ユーザー受け入れテストは、仕様と比較してバグがないことを確認することよりも、製品が顧客のニーズに適合していることを確認することよりも重要です。
1種類のテストのみを自動化する場合は、単体テストになります。統合テストは手動で行うことができ、その方法で何年にもわたって多くの主要企業によって行われていました。コンピュータで何度も行うことができる作業を手動で行うには時間がかかり、退屈でエラーが発生しやすいことは言うまでもなく、ほとんどのプロジェクトでははるかに費用がかかりますが、それは可能です。多くの場合、ユーザー受け入れテストは手動で行われます。これは、ユーザーが関心のあることをテストしながら、テストを自動化する方法を知らないことが多いためです。ユニットテストは自動化する必要があります。数分おきに頻繁にオンデマンドで数秒以内にすべてのユニットテストを実行できる必要があります。人間は、手動テストに近づくことさえできません。言うまでもなく、ユニットテストはコード内にあり、コードを介して呼び出す、つまり自動化しないと実行できません。手動でユニットテストを行うことは不可能です。
覚えておくべきことの1つは、これは主に開発者向けのフォーラムであり、テスターではないということです。統合テストは、主にテスターによって実装されます。ユニットテストは開発者によって実装されています。当然のことながら、開発者は他のタイプのテストよりも単体テストについて話します。これは、他のテストが重要だと考えていないという意味ではありません。それは彼らが実際にはそうしないことを意味しますdo it(またはそれをより少なくします)。
このシナリオでは受け入れテストが王様だと思います。
コミットが受け入れテストに違反した場合は、整理する必要があります。
受け入れテストではソフトウェアの場所がわかりますが、単体テストではわかりません。
したがって、単体テストは非常に誤った安心感をもたらす可能性があります。
自動化して迅速に実行できるものは何なので、問題はそれほど重要ではありません。
単体テストは、小さなコンポーネントが特定の方法で目的に適合しているかどうかを示し、通常は小さく、実行が高速です。小さいため、通常、自動化はかなり簡単です。
統合テストは、コンポーネントが連携して機能するかどうかを示します。通常、これらは非常に大きく、自動化するのは簡単ではないかもしれません。実行に時間がかかる場合があります。それらを自動的に実行できることには価値がありますが、それはより大きなタスクであり、とにかく頻繁に実行されることはありません。
受け入れテストは、プロジェクトが受け入れ可能かどうかを示します。これは通常、完全に自動化することは不可能です(ただし、自動化されたテストが役割を果たす可能性があります)。ソースコード自体よりも複雑ではない形式的な問題で正確かつ完全な要件を特定することは通常不可能であるためです。受け入れテストには通常、システムを使用して潜在的なユーザーが作業を行い、結果がすべての点で満足できるものであることを観察します。受け入れテストは通常1回だけ実行されるため(通常、顧客ごとに独自の受け入れテストを行う必要があります)、自動化する価値はありません。