Datadog における Test Impact Analysis の仕組み
This product is not supported for your selected
Datadog site. (
).
概要
Test Impact Analysis は Datadog のテスト影響度分析ソリューションです。テスト影響度分析は過去数十年で注目を集めてきた手法ですが、通常は実装が難しく時間もかかります。Test Impact Analysis はその複雑さを解消します。
テスト影響度分析では、各テストをリポジトリ内でテストが使用するコード ファイルの集合にマッピングします (テストごとのコード カバレッジ)。目的は、コード変更によって影響を受けないテストをスキップし、CI に費やす時間を直接削減することです。
極端な例として、README ファイルのタイプミスだけを修正するプル リクエストがあります。この PR で全テストを実行しても価値はありません。むしろ、不安定なテストが原因で CI が失敗し、マージ前にパイプラインを何度も再試行する事態になり得ます。これは開発者と CI の時間の無駄です。Test Impact Analysis を使用すれば、README ファイルだけを変更する PR ではすべてのテストをスキップできます。
他のソリューションとの違い
一部のテスト選択ソリューションはコード カバレッジ データを使用せず、機械学習で補完します。こうしたシステムは確率的に関連テストを推測するため、実際には必要だったテストを見落とし、デフォルト ブランチのビルドが失敗する可能性があります。また、機械学習ベースの手法は機能するまでに長期間のデータ収集を要するのが一般的です。Test Impact Analysis は、コード カバレッジのベースラインを取得した直後から機能し始めます。
他のテスト ソリューションもコード カバレッジを用いてテスト影響度分析を行いますが、多くは最後のコミット差分だけを考慮して実行するテストを決定します。たとえば GitHub のプル リクエストでは、マージ可否の判定に最新コミットの CI ステータスしか見ないため、すべてのコミットを CI に通さない限り、本来実行すべきテストをスキップしてしまうリスクがあります。
Test Impact Analysis はテストごとのコード カバレッジ情報と Test Optimization のデータを組み合わせ、関連する過去コミットすべてのテスト履歴を検索します。多くの言語で設定はワンクリックで完了し、結果は他の手法よりも正確かつ高精度です。
Test Impact Analysis におけるテスト選択の仕組み
Test Impact Analysis を有効化すると、テストごと (またはフレームワークによってはスイートごと) のコード カバレッジが透過的に収集され、Datadog に送信されます。
Datadog のバックエンドはその情報を用いて過去のテスト実行を検索し、特定のテストをスキップできるかどうかを判断します。Datadog が、カバレッジ対象ファイルと 追跡ファイル が現在のコミットと同一であるコミットでそのテストがパスした記録を保持している場合、そのテストはスキップされます。これは、コード変更がテストに影響を与えていないという証拠として利用されます。
次に、Datadog ライブラリはソース内で「スキップ不可」とマークされたテストをスキップ可能テスト リストから除外します。その後、テスト フレームワークに対して、スキップ可能テスト リストに残ったテストをスキップするよう指示しつつ、テストを実行します。
具体例を見てみましょう
上図は、main
から分岐した開発ブランチに複数のコミットがある例を示しています。各コミットで CI は 2 つのテスト (A と B) を実行し、結果は以下のようになりました。
- コミット 1: 両テストを実行。追跡ファイルとテスト A・B のカバレッジ対象ファイルが変更されていました。
- コミット 2: 再度両テストを実行。
- テスト A: このコミットでは追跡ファイルとカバレッジ対象ファイルに変更がなくテスト A への影響はありませんが、テスト A がパスした過去のテスト ランが存在しないため実行する必要があります。Test Impact Analysis はパスを保証できないためスキップしませんでした。今回テストがパスしたことから、テスト A が不安定なテストであることが示されました。
- テスト B: パスした実行結果がなく、さらにコミット 2 で対象ファイルが変更されたため実行されました。
- コミット 3: 追跡ファイルが変更されたため、すべてのテストを実行。
- コミット 4: 再びすべてのテストを実行。
- テスト A: 条件を満たす過去のテスト ランが存在しないため実行します。コミット 1 と 3 のテスト ランは失敗しているため利用できず、コミット 2 のテスト ランはコミット 2 から 4 の間に追跡ファイルが変更されたため利用できません。
- テスト B: 同様に条件を満たす過去のテスト ランが存在しないため実行します。コミット 1 と 2 のテスト ランは失敗しているため利用できず、コミット 3 のテスト ランはコミット 3 から 4 の間にテスト B のカバレッジ対象ファイルが変更されたため利用できません。
- コミット 5: 1 つのテストをスキップ。
- テスト A: コミット 4 のテスト ランがすべての条件を満たしているためスキップ可能です。コミット 4 から 5 の間で追跡ファイルとテスト A の影響ファイルは変更されておらず、コミット 4 でテスト A はパスしています。したがって実行してもコミット 4 と同じコード パスを通るだけで、CI に新しい情報を与えません。この場合テスト A をスキップすることで、テストを実行しないことによるパフォーマンス / コスト面のメリットに加え、テスト A が不安定なテストであるため CI の信頼性を高めるメリットも得られます。
- テスト B: カバレッジ対象ファイルがコミット 5 で変更されたため実行。
- コミット 6: 両テストをスキップ。
- テスト A: コミット 4 のパス結果によりスキップ。
- テスト B: コミット 5 のパス結果によりスキップ。
参考資料