本物のバグとフレーキーテスト(不安定なテスト)をどのように見分ければよいですか?
リトライを無効にしてテストを複数回実行し、カウントします。本物のバグはすべての実行で同じように失敗し、フレーキーテスト(不安定なテスト)は何も変更していなくても合格したり失敗したりします。以下の例は、Playwright がインストールされたマシンでまさにその動作を行い、Nexus Studio が各結果をどのように処理するかを示しています。
執筆: Nexus Studio チーム、Verdict System LLC(2026年10月27日)
1分で見分けるにはどうすればよいですか?
リトライを無効にしてテストを連続で複数回実行します。Playwright では2つのフラグを使用します。リトライによって失敗が隠されないようにする --retries=0 と、すべてのテストを6回実行する --repeat-each=6 です。その後、各テストの結果をカウントします。
- 毎回失敗した場合:反証できるまではバグとして扱ってください。ブロックされたリクエストや到達できないホストなど、環境が原因で毎回失敗することもあるため、まずはエラーを確認してください。
- 合格した回と失敗した回がある場合:フレーキーテストです。実行間でコードやテストは変更されていないため、アプリケーションまたはテストのいずれかに不安定な要因が存在します。
- 毎回合格した場合:まだ何も問題は見つかっていません。50回に1回しか発生しない不具合を見つけるには、さらに実行回数を増やすか、テストの履歴を確認する必要があります。
実行可能なサンプルで試せますか?
これを bug-or-flaky.spec.js として保存してください。最初のテストはフレーキーテストをシミュレートしており、3回に1回失敗します。2番目のテストは本物のバグです。ページには「Welcome」と表示されているのにテストは「Welcome back」を期待しているため、どの実行も合格しません。
import { test, expect } from '@playwright/test';
// Fails on its first attempt of every third run, passes otherwise: a simulated flake.
test('flaky: a slow load now and then', async ({ page }, info) => {
await page.setContent('<h1>Welcome</h1>');
expect((info.repeatEachIndex + info.retry) % 3, 'simulated slow load').not.toBe(0);
});
// Fails the same way every time: the heading says "Welcome", the test expects "Welcome back".
test('real bug: wrong heading', async ({ page }) => {
await page.setContent('<h1>Welcome</h1>');
await expect(page.locator('h1')).toHaveText('Welcome back', { timeout: 300 });
});
リトライを無効にして6回実行します:
npx playwright test --retries=0 --repeat-each=6
Playwright の結果は、8件失敗、4件合格で終了します。テストごとのカウントこそが疑問への答えであり、リストレポーターが1行ずつ出力した内容です:
flaky: a slow load now and then 4 passed, 2 failed
real bug: wrong heading 0 passed, 6 failed
次に、2回のリトライを指定して1回実行します:
npx playwright test --retries=2
Playwright は各グループに1つのテストがある状態で終了します。不安定なテスト(flaky test)は最初の試行で失敗し、リトライ #1 で成功しました。実際のリグレッション(本物のバグ)は3回の試行すべてで失敗しました。
1 failed
bug-or-flaky.spec.js:10:1 › real bug: wrong heading
1 flaky
bug-or-flaky.spec.js:4:1 › flaky: a slow load now and then
リトライで成功したということは、アプリケーションに問題がないことを意味するのでしょうか?
いいえ。リトライの成功は、試行ごとの結果が一致しなかったことを示しているにすぎません。実行結果が緑(成功)になり誰も確認しないと、競合状態、共有データ、遅延する依存関係など、アプリケーションの間欠的な不具合が見過ごされてしまいます。そしてこれらは、発見するのに最もコストがかかる不具合の一部です。不安定な結果は、無視してよい成功ではなく、ひとつの発見として捉え、テスト側に原因があると決めつけないようにしてください。
Nexus Studio は各結果をどのように処理しますか?
Nexus Studio はすべての試行を記録し、結果ごとに独自の判定(verdict)を付与するため、リトライによって不具合が単純な緑(成功)の実行結果として扱われることは決してありません。
- FLAKY: テストが失敗した後にリトライで成功し、何も修正されなかった状態です。終了コード 0 で終了するためビルドは失敗せず、レポートと History に保留事項として表示されます。
- BREACHED: 1回の試行でテストが失敗し、環境やハーネスのパターンではそのエラーを説明できない状態です。終了コード 1 で終了します。
- BREACHED_FLAKY: 過去のリトライ後に最後の試行でテストが失敗し、環境パターンではそれを説明できない状態です。終了コード 1 で終了します。バグを報告する前に各試行を比較してください。
History は各テストの実行ごとに1行を保持するため、緑、赤、再び緑となったテストは再実行の中に消え去ることなく、傾向として表示されます。flaky tests guide には、各判定が残すファイルが記載されています。
制限事項には何がありますか?
- この例のフレーク(不安定さ)は、再現するように計算処理でシミュレートされています。本物の不安定さには原因があり、それを見つけるのは今でも人の仕事です。
- 6回の実行は簡易的な確認にすぎず、統計的なデータではありません。50回に1回発生する失敗が、6回連続で成功することもあります。
- 毎回の実行で発生する失敗が、常にアプリケーションのバグであるとは限りません。ネットワークの遅延、アクセスブロックページ、ブラウザのクラッシュなどもテストを失敗させます。false failures guide では、その見分け方を説明しています。
- リトライが無効な場合、Nexus Studio における間欠的な失敗は BREACHED になります。リトライがあって初めて FLAKY と通常の失敗を区別できるためです。この分類はエラーテキストを読み取るため、予想外の判定が出た場合は metadata.json を確認してください。
どこで確認できますか?
verdicts guide では、エンジンが全14種類の判定をどのような順序で決定するかを説明しており、Evidence page では、1つの失敗したテストが残すすべてのファイルを追跡しています。30-day trial では、ご自身のテストで同じエンジンを実行できます。