Claude Codeにフレーキーテストの原因調査を任せる手順
たまに落ちるテストをClaude Codeに調べさせる指示の書き方です。N回ループで失敗率を出し、順序・並列・待機に絞り、連続成功を完了条件にしてリトライで隠さない流れを扱います。
フレーキーテスト(同じコードで通ったり落ちたりするテスト)をClaude Codeに調べさせるときは、「直して」ではなく「何回回して何回落ちたかを数えて」から頼みます。1回通っただけで直ったと判断するのが、この種の不具合でいちばん多い失敗だからです。
この記事では、再現コマンドの渡し方、N回ループで失敗率を出す方法、失敗条件の絞り込み、直し方の方向、そして「リトライで隠さない」完了条件の置き方を順に扱います。
最初の指示に入れるのは再現コマンドと「間欠的」の一言
Claude Codeの公式ドキュメントは、バグ修正の頼み方として次の3点を挙げています。再現するコマンドとスタックトレースを渡すこと、再現手順を伝えること、そしてエラーが間欠的か常に起きるかを伝えることです。
フレーキーテストでは最後の一点が効きます。「間欠的」と書かれていなければ、Claudeは1回実行して通ったところで「再現しません」と結論を出しかねません。最初の指示は次の形にします。
CIで ordering.test.ts の「注文の並び順」が10回に1回ほど落ちます。
再現コマンドは npx vitest run src/order/ordering.test.ts です。
ローカルでは1回では通ります。間欠的な失敗です。
まず原因を直さず、同じコマンドを繰り返して失敗率を測ってください。「まず直さない」と書く点が要です。測る前に直させると、効果の有無を比べる基準がなくなります。
N回ループで失敗率を出す
Claudeに任せる最初の作業は、失敗率の計測です。ループは自分で書かせても構いませんが、同じスクリプトを毎回使い回したいなら、リポジトリに置いておくと指示が短くなります。
#!/usr/bin/env bash
# scripts/repeat-test.sh 使い方: repeat-test.sh <回数> <テストコマンド...>
n="$1"; shift
fail=0
for i in $(seq 1 "$n"); do
if ! "$@" > "/tmp/run-$i.log" 2>&1; then
fail=$((fail + 1))
echo "run $i: FAIL"
fi
done
echo "failed $fail / $n"
[ "$fail" -eq 0 ]これはあくまで一例です。ポイントは3つあります。
- 失敗した回のログを回ごとに残す。成功した回と失敗した回の出力を並べて比べられる
- 最後に「何回中何回」を1行で出す。Claudeが数え間違えない
- 終了コードで全回成功かを返す。後で完了条件に使える
Claudeには「scripts/repeat-test.sh 30 npx vitest run src/order/ordering.test.ts を実行して、失敗した回のログと成功した回のログの差を読んでください」と頼みます。出力を読ませるところまでが調査です。数字だけ報告させると、原因の手がかりが残りません。
読ませるときは、何を見比べるかまで指示に書きます。
失敗した回(/tmp/run-N.log)と成功した回のログを並べて、次の3点を比べてください。
1. 各テストの開始と終了の順序(失敗した回だけ順番が違わないか)
2. 同じファイル名・ポート・DBテーブルなど、共有リソースを触っている箇所
3. 最初の例外が出る直前に、どの処理が走っていたか
差が見つかったら、該当するログの行を引用して報告してください。失敗した回のログは、例外そのものより「その直前に何をしていたか」に手がかりが残ります。引用を求めると、推測だけの報告を避けられます。
ほかのテストランナーでも考え方は同じです。Bazelなら出力の絞り方をClaude CodeでBazelのテストを回すで扱っているので、繰り返し実行するときのログ量はそちらと併せて考えられます。
失敗条件を4方向から絞る
失敗率が出たら、次は「何が変わると率が変わるか」を調べます。Claudeに1つずつ条件を変えさせ、そのたびに同じ回数を回させます。
| 切り分け | 試すこと | 率が変わったときの読み方 |
|---|---|---|
| 単独実行 | 試すことそのテストだけを回す | 率が変わったときの読み方単独で落ちないなら、他のテストの副作用や共有状態を疑う |
| 順序 | 試すこと実行順を固定する、またはシャッフルする | 率が変わったときの読み方順序で変わるなら、テスト間の依存を疑う |
| 並列度 | 試すことワーカー数を1にする | 率が変わったときの読み方1で落ちなくなるなら、ファイルやポート、DBの取り合いを疑う |
| 待機 | 試すこと処理を遅くする、またはCPUを埋める | 率が変わったときの読み方負荷で率が上がるなら、時刻頼みの待機を疑う |
実行順の固定やシャッフル、ワーカー数の指定はランナーごとに名前が違います。Claudeには「このリポジトリのランナーで順序と並列度を変えるオプションを調べて、1つずつ変えて同じ回数を回してください」と頼めば、設定ファイルとドキュメントから拾ってきます。
切り分けの流れは次の順になります。
フレーキーテスト調査の流れ
- 1
失敗率を測る
同じコマンドをN回回し、「何回中何回」を数字にします。この時点では直しません。
- 2
条件を1つずつ変える
単独実行、順序、並列度、待機の順に、1回に1つだけ変えて同じ回数を回します。
- 3
原因を示させて直す
失敗した回のログを引用させ、表で裏づけた原因だけを直します。
- 4
連続成功で完了とする
直した後に、決めておいた回数を全部通ることを確かめます。
条件は1つずつ変えます。順序と並列度を同時に変えると、どちらが効いたのか分からなくなります。この制約は、指示にそのまま書いておくのが確実です。
条件は1回に1つだけ変えてください。変えたら同じ30回を回し、
「条件 / 失敗回数」の表を作ってから、次の条件に進んでください。直す方向は「時刻」を「条件」に置き換える
絞り込みで待機が怪しいと分かったら、直し方はおおむね決まっています。固定のsleepや短いタイムアウトで「たぶんもう終わっている」を待つ書き方を、「終わったことを確かめる」書き方に置き換えます。
固定の待機(sleep 100ms など)をすべて探し、
「状態が期待どおりになるまで、上限付きで確認し続ける」書き方に直してください。
上限は今のタイムアウトより短くせず、待機の理由をコメントに1行残してください。直す対象は待機だけではありません。順序依存なら各テストで状態を作り直し、共有ポートやファイルは一時ディレクトリと空きポートに変えます。いずれも、原因が失敗率の表で裏づけられてから直すのが前提です。当たりを付けずに待機時間を延ばすと、失敗率が下がって見えるだけで原因が残ります。
Claudeが「タイムアウトを延ばしました」と報告してきたら、それは対症療法の可能性が高い合図です。原因を示す根拠(失敗した回のログのどこを見たか)を求めます。
リトライで隠さない — 完了条件を連続成功で置く
フレーキーテストでもっとも避けたいのは、リトライ設定を足して終わりにすることです。落ちる原因は残ったまま、見かけの失敗だけが消えます。そこで「直った」の定義を、先に回数で決めておきます。
Claudeに通る・落ちるで返るチェックを持たせると、自分で変更・実行・出力の読解・修正を繰り返せます。その強さの選び方は、プロンプトでの指示、/goal、Stop hookの順で厳しくなります。
プロンプトで指示する
最も手軽な方法です。完了条件と禁止事項を文にします。
完了条件は scripts/repeat-test.sh 50 で50回連続成功することです。
リトライ設定の追加、テストのスキップ、期待値の緩和は禁止です。
最後に実行コマンドと「failed 0 / 50」の出力をそのまま貼ってください。実行したコマンドとその出力を求める点は、公式ドキュメントの勧めと同じです。「全部通りました」だけでは根拠になりません。
/goalで条件を固定する
長く放置する調査なら、/goalで条件を固定できます。公式ドキュメントでは、毎ターンの後に別のモデルが条件を判定し、満たされるまでClaudeが続行するしくみだと説明されています。判定役はコマンドを自分で実行せず、会話に出ている内容だけを見ます。したがって条件は、Claudeの出力で示せる形にします。
/goal scripts/repeat-test.sh 50 npx vitest run src/order/ordering.test.ts が failed 0 / 50 で終わり、テストファイル以外の設定にリトライやスキップが追加されていない。または20ターンで停止するドキュメントは、条件に測定できる終了状態、確認方法、変えてはならないことを入れるよう勧めています。ターン数や時間の上限も条件に書けます。上の例の「20ターンで停止する」がそれです。上限を書かないと、直らない原因を延々と探し続けることがあります。
/goalのStop hookまわりの挙動はClaude Codeの/goal Stop hookが止まらないにまとめています。
Stop hookで強制する
どのセッションでも例外なく止めたいなら、Stop hookです。公式のベストプラクティスには、型チェックが通るまでターンを終わらせない設定例があります。同じ形で、繰り返しテストの終了コードを使えます。
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "scripts/repeat-test.sh 20 npx vitest run src/order/ordering.test.ts 1>&2 || exit 2"
}
]
}
]
}
}終了コード2が停止を止め、標準エラーに出した内容が「まだ終われない理由」としてClaudeに返ります。ただしツール呼び出しを挟まずに同じhookが8回続けて停止を止めると、Claude Codeは次の停止を通して、ターンを終わらせます。上限はCLAUDE_CODE_STOP_HOOK_BLOCK_CAPで変えられます。
注意点があります。このhookは、フレーキーテストに関係ない作業でも毎ターン20回の実行を走らせます。調査中だけ有効にし、終わったら外すのが現実的です。通常のテスト自動実行の設計はClaude Code hooksでテストを自動実行するが詳しいです。
CIでだけ落ちるときの進め方
手元のループでは落ちず、CIでだけ落ちるテストは、環境差から疑います。CPU数、並列度、時刻、ロケールが代表的です。CIの失敗ログを保存して渡し、環境の違いを挙げさせてから、手元で条件をそろえます。
添付の ci-failure.log は、CIで落ちた回の出力です。
手元のログと比べて、環境や実行順の違いを挙げてください。
そのうえで、CIと同じワーカー数で scripts/repeat-test.sh 30 を回し、
失敗率が変わるか確かめてください。CIのワーカー数を手元で再現できれば、手元のループでも同じ失敗が出ることがあります。出ない場合は、失敗時にログと状態を残す仕組みを先に足します。環境の差を挙げさせるだけでは、原因とは言えません。
effortは調査のときだけ上げる
公式のベストプラクティスは、/effort highや/effort xhighに上げる場面の例として、自分が書いていないコードのバグ、フレーキーテスト、古いデータ形式を読んでいる箇所を洗い出すスキーマ変更を挙げています。見落としやすい場合を多く確かめ、答える前に自分の作業をより多く検証するぶん、時間とトークンが増えます。
使い分けは次のとおりです。
- 失敗率の計測と表づくりは機械的なので、既定のeffortで足りる
- 失敗したログの読み比べと原因の仮説立ては、
highに上げる - 修正後の確認ループは、スクリプトが判定するのでeffortを戻してよい
maxは、ドキュメントによれば通常の作業では考えすぎになりやすく、highと同程度の答えに高いコストを払うことがあります。フレーキーテストの調査ならhighから試すのが無難です。
調査に時間がかかるなら、バックグラウンドで走らせる手もあります。CLIのリファレンスにはclaude --bg "investigate the flaky test"という例が載っています。放置する場合は、権限の確認で止まらないよう、実行してよいコマンドを事前に許可しておきます。
CLAUDE.mdに残す一文
毎回同じ説明をしないよう、CLAUDE.mdに繰り返し実行の入口と禁止事項を書いておきます。
# テスト
- 不安定なテストの調査: `scripts/repeat-test.sh <回数> <テストコマンド>`
- フレーキーの修正でリトライ設定・skip・期待値の緩和をしない
- 「直った」は50回連続成功のログを添えて報告するCLAUDE.mdは短く保つほうが守られやすいので、テスト全般の説明は別に置き、ここには不安定なテスト固有の3行だけを入れます。
つまずきやすい点
| 症状 | 原因の見当 | 次の一手 |
|---|---|---|
| ループでは一度も落ちず、CIでだけ落ちる | 原因の見当環境差(CPU数、並列度、時刻、ロケール) | 次の一手CIのワーカー数と同じ条件でループさせる |
| 率を測るたびにばらつく | 原因の見当回数が少ない | 次の一手回数を増やす。10回で0回失敗でも、率が1割なら通る確率は3割強ある |
| 修正後に連続成功したが翌週また落ちた | 原因の見当原因ではなく発生確率を下げただけ | 次の一手失敗した回のログから原因を示させてから直す |
| Claudeがテストごと書き換える | 原因の見当完了条件が「通ること」だけ | 次の一手期待値の緩和・skipを禁止事項に書く |
10回で全成功した確率の例は、失敗率が10%なら0.9の10乗で約35%です。数回の成功では直ったと言えず、完了条件の回数を大きめに取る理由になります。
よくある質問
再現しないテストはどう調べさせればよいですか
失敗した実行のログが手元にあれば、そのログを渡して「失敗した回にだけ起きている差」を探させます。ログが残っていなければ、まず失敗時にログと状態を残す仕組みを足し、再発を待つのが先です。
何回連続成功なら直ったと見なせますか
失敗率次第です。もとの失敗率が高いほど少ない回数で判断できます。失敗率が数%以下なら、100回前後を目安に取る考え方もあります。回数は調査の最初に出した失敗率から逆算します。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。