自動化された単体テスト、統合テスト、または受け入れテスト[終了]


29

TDDと単体テストは、現時点では大きな絶賛のようです。しかし、他の形式の自動化されたテストと比べて本当に便利なのでしょうか?

直感的には、自動化された統合テストは単体テストよりもはるかに便利だと思います。私の経験では、ほとんどのバグはモジュール間の相互作用にあるようで、各ユニットの実際の(通常は制限された)ロジックではありません。また、モジュール間のインターフェイスの変更(および変更された事前条件と事後条件)のために、しばしば回帰が起こりました。

私は何かを誤解していますか、またはなぜ統合テストに比べて単体テストがそれほど重視されているのですか?それは単に統合テストがあなたが持っているものであり、ユニットテストが開発者として適用するために学ぶ必要がある次のものであると仮定されているからです。

それとも、単体テストは、自動化の複雑さに比べて単純に最高の利益をもたらすでしょうか?

自動化された単体テスト、自動化された統合テスト、および自動化された受け入れテストでどのような経験がありますか?なぜ?

次のプロジェクトで自動化するために、テストの形式を1つだけ選択する必要がある場合、それはどのようになりますか?

前もって感謝します。


JB RainsbergerのIntegration Tests Are A Scamへの遅延リンクを追加したいと思います。統合テストが誤った経済である多くの理由を強調しています。
ティム


6
これは、3年前にこのサイトで質問されたとき、このサイトでまったく問題なかった質問を閉じるもう1つの例です。ルールが変更され、古いものをすべて捨てるコミュニティに貢献するのは本当に迷惑です!
ビジャークフロイントハンセン

回答:


34

単体テストを非常に有用にする重要な要素の1つは、高速フィードバックです。

統合/システム/機能テストでアプリを完全にカバーしたときに何が起こるかを考えてください(ほとんどの開発現場では現実からは程遠い理想的な状況です)。これらは多くの場合、専用のテストチームによって実行されます。

  • SCMリポジトリに変更をコミットし、
  • しばらくして(おそらく数日後)テスト担当者が新しい内部リリースを取得し、テストを開始します。
  • バグを見つけてバグレポートを提出します。
  • (理想的な場合)誰かがバグ報告をあなたに割り当てます。

これには数日から数週間かかる場合があります。この時点で、すでに他のタスクに取り組んでいるので、以前に書いたコードの詳細は頭にありません。さらに、通常、バグが実際に存在する場所を直接証明することさえできないため、バグを見つけて修正するにはかなりの時間がかかります。

一方、単体テスト(TDD)では

  • あなたはテストを書きます
  • テストを満たすためにいくつかのコードを書いて、
  • テストはまだ失敗します、
  • コードを見ると、通常は数秒で「おっと」体験ができます(「おっと、その状態を確認するのを忘れた!」など)
  • すぐにバグを修正してください。

これはすべて数分で起こります。

これは、統合/システムテストが役に立たないと言っているわけではありません。それらは異なる目的を果たすだけです。よく書かれたユニットテストを使用すると、コードのバグの大部分をキャッチすることができます前に、彼らはそれがそれらを見つけて修正するために、すでにかなり高価である統合相に取得します。ユニットテストでは検出が困難または不可能な種類のバグを検出するには、統合テストが必要であることは間違いありません。ただし、私の経験では、これらはまれな種類です。私が見たバグのほとんどは、メソッド内のどこかにある単純な、あるいは些細な省略によってさえ引き起こされています。

ユニットテストでは、ユーザビリティ/安全性などのインターフェイスもテストされることは言うまでもありません。したがって、デザインとAPIを改善するために非常に重要なフィードバックを提供します。どのIMHOがモジュール/サブシステム統合バグの可能性を大幅に削減できるか:APIがより簡単でクリーンなほど、誤解や省略の可能性が少なくなります。

自動化された単体テスト、自動化された統合テスト、および自動化された受け入れテストでどのような経験がありますか?なぜ?

ROIは多くの要因に依存します。おそらく最も重要なのは、プロジェクトがグリーンフィールドかレガシーかです。グリーンフィールド開発では、私のアドバイス(およびこれまでの経験)は、TDDスタイルを最初から単体テストすることです。この場合、これが最も費用対効果の高い方法であると確信しています。

ただし、従来のプロジェクトでは、十分な単体テストのカバレッジを構築することは大きな成果であり、利益を得るのに非常に時間がかかります。可能であれば、UIを介してシステム/機能テストで最も重要な機能をカバーしようとする方が効率的です。(デスクトップGUIアプリは、GUIを使用して自動的にテストするのが難しい場合がありますが、自動テストサポートツールは徐々に改善されています...)。これにより、粗いが効果的なセーフティネットが迅速に得られます。その後、アプリの最も重要な部分を中心にユニットテストを徐々に構築していきます。

次のプロジェクトで自動化するテストの形式を1つだけ選択しなければならなかった場合、どちらになりますか?

それは理論的な質問であり、私はそれが無意味だと思う。すべての種類のテストは、優れたソフトウェアエンジニアのツールボックスで使用され、これらすべてには、かけがえのないシナリオがあります。


2
ユニットテストの「高速フィードバック」の場合は+1。また、継続的インテグレーションサーバーでポストコミットとして実行する場合にも非常に便利です。
フランクシェラー

1
「すべての種類のテストは、優れたソフトウェアエンジニアのツールボックスで使用できます。これらすべてには、かけがえのないシナリオがあります。」-そのためだけに何度か投票できたらいいのに!理想的なテストツール/方法を1つだけ見つけて、それをあらゆる場所に適用できると考える人は、私を疲れさせています。
ptyx

8

すべてのタイプのテストは非常に重要であり、システムのさまざまな側面が仕様内にあることを確認します。したがって、「1つのタイプのテストを選択しなければならない場合...」という逆方向に作業することはできません。単体テストは、統合テストや個人によるインタラクティブなテストとは異なるフィードバックを提供します。

テストの種類/利点は次のとおりです。

  • ユニットテスト-ユニットが期待どおりに動作していることを確認します。すべてのインターフェイスについてプロバイダーとコンシューマの両方の契約をテストします。これはかなり簡単に自動化できます。境界条件などもチェックします。
  • 統合テスト-ユニットが連携して動作していることを確認します。これは主に設計をテストするためです。ここで何かが壊れた場合、ユニットテストを調整して、それが再び発生しないことを確認する必要があります。
  • システムテスト-システムが要件/仕様を満たしていることを確認します。通常、人々はこのタイプのテストを行います。
  • 受け入れテスト-クライアントはこれを行い、最終製品が広告されていることを確認します。

オプションですが推奨されるテスト:

  • ユーザーエクスペリエンステスト:システムテストから適切なフィードバックを得ていますが、クライアントの人に特定のプレリリースをプレビューしてもらうと、手遅れになる前に変更する必要があるかどうかを判断するのに役立ちます。

単体テストが統合テストよりも優れている理由を理解するためには、包括的にする必要のある追加のテストの規模を理解する必要があります。ユニットAのすべての可能な結果について、テストが必要です。ユニットBについても同じです。今度は、両方がより完全なソリューションのために連携する場合、テストの数は組み合わせです。つまり、ユニットAとユニットBの間の相互作用のすべての順列をテストするには、A * Bテストが必要です。ユニットCを追加すると、トリオのテスト数はA * B * Cになります。

ここで、インターフェイスとオブジェクト境界の概念が非常に重要になります。インターフェイスは特定の契約を表します。インターフェイスの実装者は、特定の方法で動作することに同意します。同様に、インターフェースのコンシューマーは、特定の方法で実装を使用することに同意します。インターフェイスを実装するすべてのクラスを収集するテストを記述することにより、各実装がインターフェイスコントラクトを監視していることを簡単にテストできます。それは方程式の半分です。残りの半分は、消費者側をテストすることです。ここで、モックオブジェクトが再生されます。モックは、相互作用が常に仕様内になるように構成されています。この時点で必要なのは、実装者と消費者の契約が正しいことを確認するためのいくつかの統合テストだけです。


「システムのテスト-システムが要件/仕様を満たしていることを確認します。通常、このタイプのテストを行います」。システム/機能/別名「エンドツーエンド」/別名高レベル統合テストは、自動化にも適しています。
MiFreidgeim SO停止ビーイング悪

3

これらは、さまざまな目標を持つさまざまなツールです。

  • 単体テストは設計ツール(TDD)であり、リファクタリングのほぼ前提条件です。

  • 統合テストは、プロジェクトの進行状況を視覚化するのに最適であり、回帰バグを回避するのにも最適です。

覚えておくべき点は、統合テストでは実際に設計することはできず、単体テストでは回帰が見られないということです。


@統合テストで実際に設計することはできません。また、単体テストではリグレッションは見つかりません。まさに!
チャンキーPathak

単体テストでは、変更された共有ヘルパーメソッドなど、リファクタリングによって引き起こされる回帰を見つけることができます。ただし、統合テストははるかに優れています。
StuperUser

統合テストについての第二の点は、「システム/機能性」(別名「エンドツーエンド」)試験含ま
MiFreidgeim SO停止さ悪

完全に同意しました。数年前にスティーブ・サンダーソンによって同様の指摘がなされました。2009年のブログ投稿blog.stevensanderson.com/2009/08/24/の「目標-最強のテクニック」の表をご覧ください。
マークA.フィッツジェラルド

1

私は健全性チェックにSeleniumを広範囲に使用しました。

大規模なWeb公開会社では、新しいリリースが作成されたとき、通常、テストスクリプトに従って、すべてのサイトファミリを訪問し、すべてが正常であることを確認するのに、約1〜2時間で3人のテスターがかかりました。Seleniumを使用して、テストを自動化し、複数のマシンとブラウザーに配布することができました。現在、テストスクリプトを実行すると、3台のPCが同じことを自動的に行い、きれいなレポートを出力するのに約10分かかります。

セレンの素晴らしいところは、XUnit、TestNG、MSTestなどの単体テストフレームワークと連携できることです。

私の経験では、それは非常に貴重でしたが、そのような設定はプロジェクトとチームに本当に依存するため、ROIは間違いなく異なります。


1

通常、最善のROIは、そのタイプのバグを見つけることができる最も早いテストです。

単体テストでは、1つのメソッド、または1つのコンポーネントに存在するほとんどのバグを見つける必要があります。通常数分で修正できるバグが見つかり、総所要時間は1時間未満です。非常に安価なテスト、非常に安価なバグを見つけて修正します!これらのバグが統合テストに組み込まれた場合、そのバグが別のバグによって隠されていないことを前提として、ターンアラウンドは1日のようになります(テストの実行は夜間に行われることがよくあります)。さらに、最初のバグのあるコードに対して他のコードが記述されているため、より多くのバグが導入される可能性があります。加えて、再設計はより多くのコードに影響を与えます。また、より多くのバグを許可するということは、統合テストを完了する前にさらに多くのテストを実行する必要があることを意味します。貧弱な単体テストは、多くの場合、長く、面倒で、高価なものです統合サイクルをテストします。単体テストをスキップすると開発時間が半減する可能性がありますが、テストには少なくとも3〜4倍の時間がかかり、プロジェクト全体の長さが2倍になり、IMEを単体テストする場合よりも品質が低下します。

統合テストは通常​​、統合バグを見つけることができる最も早い実際のテストです(ただし、レビュープロセスでは、ソフトウェアの作成前またはコードのテスト前にバグを見つけることができます)。ソフトウェアをユーザーやリリースに見せ始める前に、それらのバグを見つけたいと思っています。最後の瞬間にバグを修正する(またはホットフィックスする)ことは非常に費用がかかるからです。(定義により)統合するために複数の作業コンポーネントが必要なため、修正するのが安価な場合、それらのバグを早期に見つけることはできません。より興味深いテストを開始する前に、相互作用部分とは関係のないバグ(マイナータイプミスなど)を最初に解決する必要がある場合、統合テストの速度が低下します。

ユーザー受け入れテストは、プロジェクトの最後に期待と実際のソフトウェアの間に大きなギャップを見つけるリスクを軽減するために、顧客が望むことをソフトウェアが確実に行うことを確認しています!)。テストのこの段階に到達するまでに、少なくとも仕様と比較して、製品のバグのほとんどが既に発見されていると本当に信じるべきです。ユーザー受け入れテストとは、仕様と比較してバグがないことを確認することよりも、製品が顧客のニーズに適合することを確認することです。

1つのタイプのテストのみを自動化する場合は、単体テストになります。統合テストは手動で行うことができ、多くの大手企業が長年にわたってそのように行ってきました。退屈でエラーが発生しやすいのは言うまでもなく、コンピューターで何度も行うことができる作業を手動で行うのはより時間がかかり、ほとんどのプロジェクトでははるかに高価ですが、行うことができます。ユーザー受け入れテストは、多くの場合手動です。ユーザーは、関心のあることをテストしながらテストを自動化する方法を知らないことが多いためです。単体テストは自動化する必要があります。オンデマンドで数秒以内に、数分ごとにすべてのユニットテストを実行できる必要があります。人間は手動テストでさえ近づくことができません。ユニットテストはコード内にあり、コードを介して呼び出すこと、つまり自動化しないと実行できないことは言うまでもありません。

心に留めておくべきことの1つは、これがテスターではなく開発者向けのフォーラムであることです。統合テストは主にテスターに​​よって実装されます。単体テストは開発者によって実装されます。当然のことながら、開発者は他のタイプのテストよりも単体テストについて詳しく話します。これは、彼らが他のテストが重要だとは思わないという意味ではありません。それはちょうど、彼らが実際にはないことを意味しません、それを(以下多くの場合、それを行います)。


特に最後の段落に感謝しますが、私はそれを考えませんでした。
Bjarkeフロイント・ハンセン

参考までに、私はあなたがそれを読んだので答えを更新しました-私は元の質問を十分に読んでいないことに気付きました
エセル・エヴァンス

@EthelEvans、ユニットテストの優先順位に関するあなたの理由は、新しいプロジェクトにとって正しいです。テストカバレッジの自動化を考慮せずに作成されたレガシープロジェクトの場合、システム/機能/高レベル統合テストが最も重要です。Programmers.stackexchange.com/a/39370/31574回答の最後の部分を参照してください。
MiFreidgeim SO停止ビーイング悪

@MichaelFreidgeim、最終的には、インターフェイスの安定性に依存します。高レベルのテストを自動化すると、それらがすぐに古くなった場合、すぐに法外な保守コストが発生する可能性があります。この場合は、自動化を低くして安定性を構築し、E2Eおよび統合テストの探索的テスト(おそらくセッションベースまたはチェックリストベース)を使用して、不快な自動メンテナンスコストの発生を防ぎます。ただし、すべてのレガシープロジェクトが安定したインターフェイスを持っているわけではありません-特に、それらが積極的にリファクタリングまたは再設計されている場合。
エセルエヴァンス

1

このシナリオでは、受け入れテストが重要だと感じています。

コミットが受け入れテストに違反した場合は、整理する必要があります。

受け入れテストでは、ソフトウェアの場所がわかりますが、単体テストではわかりません。

したがって、単体テストは非常に誤った安心感をもたらします。


0

質問は、自動化して迅速に実行できるものほど重要ではありません。

単体テストは、小さなコンポーネントが特定の方法で目的に適合しているかどうかを示し、通常は小さくて実行が迅速です。小さいので、通常は自動化がかなり簡単です。

統合テストは、コンポーネントが連動するかどうかを示します。通常、それらははるかに大きく、自動化するのは簡単ではありません。実行に時間がかかる場合があります。それらを自動的に実行できることには価値がありますが、それはより大きなタスクであり、とにかくそれほど頻繁には実行されません。

受け入れテストは、プロジェクトが受け入れられるかどうかを示します。これは通常、完全に自動化することは不可能です(ただし、自動化されたテストが役割を果たす可能性があります)。通常、ソースコード自体ほど複雑ではない形式的な問題で正確かつ完全な要件を特定することは不可能です。受け入れテストには、通常、潜在的なユーザーがシステムを使用して、結果がすべての点で満足できることを観察することが含まれます。これは通常、部分的に主観的です。通常、受け入れテストは1回実行されるため(異なる顧客は通常、独自の受け入れテストを行うことを望むでしょう)、実際には自動化する価値はありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.