回帰テスト(まれに非回帰テスト[ 1 ])は、以前に開発およびテストされたソフトウェアが変更後も期待どおりに動作することを確認するために、機能テストと非機能テストを再実行することです。 [ 2 ]そうでない場合は、回帰と呼ばれます。
回帰テストが必要となる可能性のある変更には、バグ修正、ソフトウェアの機能強化、構成変更、さらには電子部品(ハードウェア)の交換などが含まれます。[ 3 ]回帰テストスイートは発見された欠陥ごとに大きくなる傾向があるため、テスト自動化が頻繁に用いられます。適切なテストのサブセットを決定するために、変更影響分析が実行される場合もあります(非回帰分析[ 4 ])。
ソフトウェアが更新または変更されたり、変更されたターゲット上で再利用されたりすると、新たな不具合が発生したり、以前の不具合が再発したりすることはよくあります。
修正が不適切なバージョン管理(または単純な人的ミス)によって失われると、問題が再発することがあります。多くの場合、問題の修正は「脆弱」であり、最初に問題が発見された狭いケースでは問題を解決しますが、ソフトウェアのライフサイクル中に発生する可能性のあるより一般的なケースでは解決しません。ある領域の問題に対する修正が、意図せず別の領域でソフトウェアのバグを引き起こすこともよくあります。
機能を再設計する際に、元の機能の実装で発生したのと同じ間違いが再設計でも発生する可能性があります。ほとんどのソフトウェア開発の状況では、バグが発見され修正されたら、そのバグを明らかにするテストを記録し、プログラムへのその後の変更後にそのテストを定期的に再実行することが、良いコーディングの実践であると考えられています。[ 5 ]
これはプログラミング技術を用いた手動テスト手順によって行われる場合もあるが、多くの場合、自動テストツールを使用して行われる。[ 6 ]このようなテストスイートには、テスト環境がすべての回帰テストケースを自動的に実行できるようにするソフトウェアツールが含まれている。多くのプロジェクトでは、指定された間隔ですべての回帰テストを再実行し、失敗(回帰または古いテストを示唆する可能性がある)を報告する自動化された継続的インテグレーションシステムを採用している。[ 7 ]
一般的な戦略としては、コンパイルが成功するたびに(小規模プロジェクトの場合)、毎晩、または週に一度、このようなシステムを実行するという方法があります。これらの戦略は外部ツールで自動化できます。[ 8 ]
回帰テストは、エクストリームプログラミングソフトウェア開発手法の不可欠な部分です。 [ 9 ]この手法では、設計ドキュメントの代わりに、ソフトウェア開発プロセスの各段階を通してソフトウェアパッケージ全体に対する広範囲で反復可能かつ自動化されたテストが行われます。回帰テストは、機能テストが完了した後に、他の機能が正しく動作していることを確認するために行われます。
企業の世界では、従来、回帰テストは開発チームが作業を完了した後にソフトウェア品質保証チームによって実施されてきました。しかし、この段階で発見された欠陥は修正に最もコストがかかります。この問題は、ユニットテストの台頭によって対処されています。開発者は開発サイクルの一部として常にテストケースを作成してきましたが、これらのテストケースは一般的に機能テストまたは意図した結果のみを検証するユニットテストのいずれかでした。開発者テストは、開発者にユニットテストに集中し、肯定的なテストケースと否定的なテストケースの両方を含めることを促します。[ 10 ]
回帰テストの手法には、以下のようなものがあります。
この手法は、現在のプログラムのすべてのテストケースをチェックして、その整合性を確認します。すべてのテストケースを再実行する必要があるためコストはかかりますが、変更されたコードによるエラーがないことを保証します。[ 11 ]
すべて再テストとは異なり、この手法では、テストスイートの一部を選択するコストが、すべて再テストの手法よりも低い場合に、テストスイートの一部を実行します(すべて再テストのコストのため)。[ 11 ]
テストスイートの欠陥検出率を高めるために、テストケースに優先順位を付けます。テストケースの優先順位付け手法では、優先順位の高いテストケースが優先順位の低いテストケースよりも先に実行されるようにテストケースをスケジュールします。[ 11 ]
この手法は、回帰テストの選択とテストケースの優先順位付けを組み合わせたものです。[ 11 ]
回帰テストは、ソフトウェアの既存の機能に変更が加えられた場合、またはソフトウェアにバグ修正があった場合に実行されます。回帰テストは複数のアプローチで実行できます。すべてのテストを行うアプローチを採用すると、ソフトウェアに加えられた変更が既存の機能に影響を与えていないことが保証されます。[ 12 ]
アジャイルソフトウェア開発では、ソフトウェア開発ライフサイクルが非常に短く、リソースが限られており、ソフトウェアの変更が非常に頻繁に行われるため、回帰テストは多くの不必要なオーバーヘッドを引き起こす可能性があります。[ 12 ]
サードパーティ製のブラックボックスコンポーネントを使用する傾向のあるソフトウェア開発環境では、サードパーティ製コンポーネントの変更がシステムの他の部分に干渉する可能性があるため、回帰テストの実行は困難になる場合があります(サードパーティ製コンポーネントは未知のエンティティであるため、回帰テストの実行は困難です)。[ 12 ]
回帰テストは、プログラムの正しさをテストするだけでなく、出力の品質を追跡するためにもよく使用されます。 [ 13 ]例えば、コンパイラの設計では、回帰テストによってコードサイズやテストスイートケースのコンパイルと実行にかかる時間を追跡できます。
また、新たなバグが発生すると、プログラムの保守には、他のプログラミング言語と比べて、記述されたステートメントごとに遥かに多くのシステムテストが必要になります。理論的には、修正を行うたびに、以前にシステムに対して実行されたテストケースのバッチ全体を実行し、システムが予期せぬ形で損傷を受けていないことを確認する必要があります。実際には、このような回帰テストは理論的な考え方に近似する必要があり、非常にコストがかかります。
—フレッド・ブルックス著『人月の神話』122ページ
回帰テストは、ユニットテストからシステム統合テストまで、あらゆるレベルで実行できます。機能テストは、さまざまな入力を使用してプログラム全体を実行します。これらのテストは、繰り返し実行する必要があるため、多くの場合自動化されており、コンパイラスイートの一部ではないテストツールを使用して実行される場合があります。非機能テストは、パフォーマンス、セキュリティ、信頼性などの側面を評価します。非機能回帰テストの実施には、追加の課題があります。たとえば、パフォーマンスの変化を検出することは、統計的に複雑な場合が多く、[ 14 ]セキュリティの問題は通常、個々のコードの変更ではなく、ソフトウェアエコシステムの脆弱性から発生します。[ 15 ]
回帰問題に焦点を当てたテスト活動は、(非)回帰テストと呼ばれます。通常、「非」は省略されます。