CLAUDE LABEN
FORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられていますFORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられています
記事一覧/Claude Code
Claude Code/2026-05-01中級

Claude Code で flaky test を体系的に潰す段階的アプローチ

「再実行したら通った」で済ませてきた flaky test を、Claude Code を使って体系的に分析・修正する手順を紹介します。原因分類から再現スクリプトまで、本番運用で機能しているパターンをまとめました。

Claude Code198テスト自動化4flaky testCI/CD18デバッグ3

CI が赤くなって Slack に通知が飛んでくる。ログを開いてみると、見覚えのあるテストが落ちています。Retry を押すと通る。「またあのテストか」と思いながら閉じる ── この繰り返しに心当たりはないでしょうか。

flaky test (不安定テスト) は、放置するとチーム全体の CI への信頼を蝕みます。「どうせ再実行で通る」という空気が生まれた瞬間、本当に直すべきリグレッションも「flaky だろう」で片付けられはじめます。私は過去に、リリース直前にこの空気のまま本番デプロイしてしまい、ユーザー報告で初めて気づくというトラブルを経験しました。それ以来、flaky test は「あとで直す」ではなく「最優先で原因を特定する」ものとして扱っています。

Claude Code を使って flaky test を体系的に潰していく実践的な手順を順番にご紹介します。一発で原因が分かる魔法のコマンドは存在しませんが、原因の分類さえできれば、Claude Code はかなり強力な相棒になってくれます。

flaky test の正体は「実行順序・タイミング・状態」のいずれか

まず大事なのは、flaky test は単一の現象ではないという認識です。「たまに落ちるテスト」と一括りにしても、原因はおおむね次の3カテゴリに分類できます。

実行順序依存: テスト A の後に B を実行すると落ちるが、B 単体では通る。グローバル状態 (DB、シングルトン、環境変数) のリセット漏れが典型です。

タイミング依存: 非同期処理やアニメーション、ネットワーク待機の不安定さ。setTimeout(500) で待つようなコードは、CI 環境のロード次第で確実に裏切ります。

外部状態依存: 現在時刻、乱数、外部 API、ファイルシステムなど、実行ごとに変わる要素を直接参照していること。

修正の方針はカテゴリごとにまったく違います。だからこそ、Claude Code に丸投げする前に「どのカテゴリか」を判別するのが第一歩です。

Claude Code への最初の依頼は「分類」

私は flaky test を見つけたら、まず Claude Code にこう依頼します。

このテストファイルを読んで、以下の3カテゴリのどれに該当する可能性が高いか判定してください。
 
1. 実行順序依存 (グローバル状態の汚染)
2. タイミング依存 (非同期/待機処理)
3. 外部状態依存 (時刻/乱数/API/ファイル)
 
該当箇所を行番号付きで指摘し、根拠も簡潔に説明してください。
複数該当する場合は優先度の高い順に。
 
target: tests/integration/payment.test.ts

ポイントは「修正してください」ではなく「分類してください」と頼むこと。最初から修正を依頼すると、Claude Code は最も目立つ候補に対して fix を提案してきます。それが本当の原因とは限りません。flaky test の修正で最も避けたいのは「症状を抑えるだけのコード」を入れて、再発時に原因究明が困難になることです。

ステップ1: 再現スクリプトを Claude Code に書かせる

分類ができたら、次は再現性の確保です。flaky test を直す前に「100% 再現する手段」を手に入れることが、地味ですが最大の前進になります。

カテゴリ別に効くアプローチを紹介します。

実行順序依存の場合: テストの実行順をシャッフルして、複数回ループさせる。

# Vitest の例
npx vitest run --sequence.shuffle --sequence.seed=12345
 
# Jest の例
jest --testSequencer=./scripts/random-sequencer.js

Claude Code に「Vitest のテストをランダム順で 50 回実行して、失敗したシードと失敗テスト名を収集するスクリプトを書いて」と頼むと、次のような bash スクリプトを返してきます。

#!/usr/bin/env bash
# scripts/find-flaky.sh — 実行順依存の flaky test を炙り出す
set -uo pipefail
 
ITERATIONS="${1:-50}"
LOG_DIR="./.flaky-logs"
mkdir -p "$LOG_DIR"
 
> "$LOG_DIR/failures.tsv"
echo -e "iter\tseed\tfailed_test" > "$LOG_DIR/failures.tsv"
 
for i in $(seq 1 "$ITERATIONS"); do
  SEED=$RANDOM
  echo "▶ iteration $i (seed=$SEED)"
 
  if ! OUTPUT=$(npx vitest run --sequence.shuffle --sequence.seed="$SEED" --reporter=json 2>&1); then
    # 失敗テスト名を JSON から抽出 (jq が必要)
    FAILED=$(echo "$OUTPUT" | jq -r '.testResults[].assertionResults[] | select(.status=="failed") | .fullName' 2>/dev/null | tr '\n' ',')
    echo -e "${i}\t${SEED}\t${FAILED}" >> "$LOG_DIR/failures.tsv"
  fi
done
 
echo ""
echo "=== 失敗ログ ==="
cat "$LOG_DIR/failures.tsv"

期待する出力は次のようになります。

=== 失敗ログ ===
iter  seed   failed_test
3     8421   integration > payment > should reject expired card,
12    19284  integration > payment > should reject expired card,
27    4477   integration > payment > should reject expired card,

同じテストが特定のシードでだけ落ちていれば、ほぼ確実に実行順依存です。逆にランダムに別テストが落ちていれば、共有リソースが汚染されている可能性が高い。

タイミング依存の場合: 同じテストを連続で実行して落ちる頻度を測ります。シャッフルは不要で、--repeat=100 のような繰り返しオプションを使うか、bash で単純に 100 回ループさせる方が早いです。

外部状態依存の場合: テスト実行時刻を変えたり、ネットワークを切ったりして、外部依存ごとに切り分けます。

ステップ2: 「正しい修正」と「ごまかしの修正」を区別する

再現できたら修正に入ります。ここで Claude Code に「直して」と頼むと、たいてい以下のいずれかの提案が返ってきます。

  • リトライロジックを追加する (expect(...).toEventuallyEqual(...) 的なもの)
  • setTimeout で待機時間を延ばす
  • そのテストだけ it.skip する

これらはすべて症状を隠す修正であって、原因を直す修正ではありません。私は Claude Code に対して、次のような明示的な制約を伝えます。

flaky の根本原因を直してください。以下のアプローチは禁止です。
 
- 待機時間を延ばす (sleep, setTimeout, waitFor の timeout 増加)
- リトライ回数を増やす
- テストをスキップする
- try/catch で失敗を握りつぶす
 
代わりに、以下のいずれかで修正してください。
 
A. テスト間で共有されている状態を beforeEach/afterEach で確実にリセットする
B. 非同期処理の完了を、時間ではなくイベント/状態で待つ
C. 外部依存を時刻固定 / モック / シードで決定論的にする

この制約をかけるだけで、提案の質が体感的にかなり変わります。とくに「時間ではなくイベントで待つ」という指示は、Playwright や Testing Library 系のテストで効果が大きいです。

よくある修正パターンの Before/After

Before (タイミング依存・脆弱):

// アニメーション完了を時間で待つ
await page.click("#open-modal");
await new Promise((r) => setTimeout(r, 500)); // ← 500ms で足りる保証はない
expect(await page.isVisible("#modal-content")).toBe(true);

After (状態で待つ・堅牢):

// モーダルが「実際に表示されるまで」待つ
await page.click("#open-modal");
await page.waitForSelector("#modal-content[data-state='open']", {
  state: "visible",
  timeout: 5000, // 上限ガードのみ
});
expect(await page.isVisible("#modal-content")).toBe(true);

waitForSelectortimeout は「最大何秒待つか」のガードであって、毎回その時間待つわけではありません。状態が満たされた瞬間に進むので、CI の負荷が高い日にも強くなります。

Before (外部状態依存・乱数):

test("ID が一意に発行される", () => {
  const id1 = generateId();
  const id2 = generateId();
  expect(id1).not.toBe(id2); // たまたま衝突したら落ちる
});

After (シード固定で決定論):

import { mockRandom } from "./helpers/mock-random";
 
test("連続生成しても ID が衝突しない (seeded)", () => {
  const restore = mockRandom([0.1, 0.2, 0.3]); // 決定論的な値を返す
  try {
    const ids = Array.from({ length: 100 }, generateId);
    expect(new Set(ids).size).toBe(100);
  } finally {
    restore();
  }
});

「衝突しない」という性質を確認したいなら、ランダム性そのものは別の責務として切り出して、テストでは決定論的に振る舞わせる ── という設計が王道です。

ステップ3: 修正を「再発しない仕組み」に昇華する

個別のテストを直しても、同じパターンの flaky が後から増えてしまっては意味がありません。私はチームで運用するうえで、次の3つを最低限のセットとして導入することにしています。

1. CI でランダム順実行を常設する: 毎回固定順で通っていても、ランダム順で初めて落ちる依存はよくあります。最初は「壊れたテストを毎日見せられて辛い」と感じますが、それこそが今まで見えていなかった負債なので、避けずに直していきます。

2. 待機系のヘルパーをラップする: チームのコードベースで setTimeout が直接使われているテストを、Claude Code に検出させます。

tests/ 配下のすべてのファイルから、以下のパターンを抽出してください。
 
- new Promise(resolve => setTimeout(resolve, ...))
- await sleep(...)
- await new Promise((r) => setTimeout(r, ...))
 
ファイルパスと行番号、待機ミリ秒数を表形式で。

返ってきた一覧をもとに、waitForCondition のようなチーム共通ヘルパーへ徐々に置き換えていきます。Claude Code は機械的な置換に強いので、こうした「広く浅い掃除」がとても捗ります。

3. flaky 履歴を可視化する: 一度修正した flaky test がまた落ちはじめたら、それは別の原因のサインです。CI のテスト結果を集計するダッシュボードを用意するか、最低限「直近30日でリトライされた回数が多い順にリスト化する」だけでも、再発の早期発見につながります。

一緒に押さえておきたい記事

脆いテストの設計上の根本原因が章を追って整理されていて、Claude Code への依頼文を書くときの語彙も増えます。

次の一歩

明日 CI を見たときに「またあのテストか」と思ったら、リトライボタンを押す前に Claude Code を開いて、まず3カテゴリのどれに該当するか分類だけ依頼してみてください。修正よりも、「この flaky はタイミング依存だ」と言語化できることのほうが、実は大きな前進です。そこから先は、この記事で紹介した制約 (待機・リトライ・スキップを禁じる) をかけながら、根本原因に手を入れていけば十分です。

シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

Claude Code2026-04-17
「仕様書がテストになり、テストが実装になる」 — Claude Code で実現する Spec-Driven Development
仕様書を書くだけで Claude Code がテスト・実装・ドキュメントを自動生成する Spec-Driven Development の実践ガイド。YAML仕様フォーマット・TDD自動化・CI/CD統合まで、実際のコードで体系的に解説します。
Claude Code2026-06-18
SessionEnd フックに後片付けとログ記録を寄せる
Claude Code に追加されたポストセッションフックを使い、セッション終了後の一時ファイル削除とログ記録を自動化する方法を、複数リポジトリを順に処理する運用の実例とともにまとめました。
Claude Code2026-06-14
PR ごとに走る CI が月次クレジットを溶かす前に — Claude Code GitHub Actions の消費を抑える3層ガード
6/15 から Claude Code GitHub Actions は繰越なしの月次クレジットで課金されます。全PRでレビューを走らせると月初に枯れます。実行条件・1回の上限・消費の可視化という3層で、CIを止めずに消費を抑えた設計と動くワークフローをまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →