Communitygithub.com

AI回帰テスト

AI支援開発における回帰テスト戦略。データベース依存のないサンドボックスモードのAPIテスト、自動バグチェックワークフロー、同じモデルがコードの作成とレビューを行うことによるAIの盲点を捉えるパターンを提供します。AI支援コードに回帰テストを追加する場合や、同じモデルが変更の作成とレビューの両方を行った場合に使用します。

AI回帰テスト とは?

AI回帰テストは、AIエージェントがコードの作成とレビューの両方を行う開発環境に特化したテスティングパターン集です。AIは自身の前提を持ってコードを記述し、その同じ前提でレビューを行うため、システム的な盲点が発生します。このスキルは、サンドボックスモードを活用したデータベース不要の高速APIテスト手法、バグ発見時の即時テスト作成手順、そして最も発生頻度の高い「サンドボックス/プロダクションパスの不一致」をはじめとする一般的な回帰パターンを網羅しています。Vitest + Next.js App Router環境向けに最適化されており、Claude Code、Cursor、CodexなどのAIエージェントで使用できます。ワークフローは自動テストの実行(npm run test、npm run build)を最初の必須ステップとし、その後にAIコードレビュー、そして修正ごとの回帰テスト作成へと進みます。目指すのはカバレッジ率ではなく、特定のバグの再発防止です。

対応✓Claude Code✓Codex CLI✓Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/ai-regression-testing

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

AI回帰テスト は何をしますか?

AI支援開発向けに設計されたテスティングパターン。同じモデルがコードを作成しレビューすることで発生する、自動テストでのみ発見可能な系統的な盲点を捉えます。

有効化のタイミング

  • AIエージェント(Claude Code、Cursor、Codex)がAPIルートやバックエンドロジックを変更した場合
  • バグが発見され修正された場合 — 再発防止が必要な場合
  • プロジェクトにデータベース不要のテストで活用できるサンドボックス/モックモードがある場合
  • コード変更後に /bug-check または類似のレビューコマンドを実行する場合
  • 複数のコードパスが存在する場合(サンドボックス vs プロダクション、フィーチャーフラグなど)

中核となる問題

AIがコードを作成し、その同じコードをレビューする場合、両方のステップで同じ前提を持ち込みます。これにより、予測可能な障害パターンが発生します。

AIが修正を書く → AIが修正をレビューする → AI「正しいようです」→ バグがまだ存在する

実際の例(本番環境で観測):

修正1: notification_settings をAPIレスポンスに追加
  → SELECTクエリに追加するのを忘れる
  → AIがレビューしたが見逃した(同じ盲点)

修正2: SELECTクエリに追加
  → TypeScriptビルドエラー(生成された型にカラムが存在しない)
  → AIは修正1をレビューしたがSELECTの問題に気づかなかった

修正3: SELECT * に変更
  → プロダクションパスを修正したが、サンドボックスパスを忘れた
  → AIがレビューしたがまたもや見逃した(4回目)

修正4: テストが初回実行で即座に捕捉 PASS:

パターン: サンドボックス/プロダクションパスの不一致 は、AIが導入する回帰の第1位です。

サンドボックスモードのAPIテスト

AIフレンドリーなアーキテクチャのほとんどのプロジェクトには、サンドボックス/モックモードがあります。これが高速でデータベース不要のAPIテストの鍵です。

セットアップ(Vitest + Next.js App Router)

// vitest.config.ts
import { defineConfig } from "vitest/config";
import path from "path";

export default defineConfig({
  test: {
    environment: "node",
    globals: true,
    include: ["__tests__/**/*.test.ts"],
    setupFiles: ["__tests__/setup.ts"],
  },
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "."),
    },
  },
});
// __tests__/setup.ts
// サンドボックスモードを強制 — データベース不要
process.env.SANDBOX_MODE = "true";
process.env.NEXT_PUBLIC_SUPABASE_URL = "";
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY = "";

Next.js APIルート用テストヘルパー

// __tests__/helpers.ts
import { NextRequest } from "next/server";

export function createTestRequest(
  url: string,
  options?: {
    method?: string;
    body?: Record<string, unknown>;
    headers?: Record<string, string>;
    sandboxUserId?: string;
  },
): NextRequest {
  const { method = "GET", body, headers = {}, sandboxUserId } = options || {};
  const fullUrl = url.startsWith("http") ? url : `http://localhost:3000${url}`;
  const reqHeaders: Record<string, string> = { ...headers };

  if (sandboxUserId) {
    reqHeaders["x-sandbox-user-id"] = sandboxUserId;
  }

  const init: { method: string; headers: Record<string, string>; body?: string } = {
    method,
    headers: reqHeaders,
  };

  if (body) {
    init.body = JSON.stringify(body);
    reqHeaders["content-type"] = "application/json";
  }

  return new NextRequest(fullUrl, init);
}

export async function parseResponse(response: Response) {
  const json = await response.json();
  return { status: response.status, json };
}

回帰テストの作成

主要な原則: 正常に動作するコードではなく、発見されたバグに対してテストを書く。

// __tests__/api/user/profile.test.ts
import { describe, it, expect } from "vitest";
import { createTestRequest, parseResponse } from "../../helpers";
import { GET, PATCH } from "@/app/api/user/profile/route";

// 契約を定義 — レスポンスに必須のフィールド
const REQUIRED_FIELDS = [
  "id",
  "email",
  "full_name",
  "phone",
  "role",
  "created_at",
  "avatar_url",
  "notification_settings",  // ← バグが見つかった後に追加
];

describe("GET /api/user/profile", () => {
  it("すべての必須フィールドを返す", async () => {
    const req = createTestRequest("/api/user/profile");
    const res = await GET(req);
    const { status, json } = await parseResponse(res);

    expect(status).toBe(200);
    for (const field of REQUIRED_FIELDS) {
      expect(json.data).toHaveProperty(field);
    }
  });

  // 回帰テスト — この特定のバグはAIによって4回導入された
  it("notification_settings が undefined ではない(BUG-R1回帰)", async () => {
    const req = createTestRequest("/api/user/profile");
    const res = await GET(req);
    const { json } = await parseResponse(res);

    expect("notification_settings" in json.data).toBe(true);
    const ns = json.data.notification_settings;
    expect(ns === null || typeof ns === "object").toBe(true);
  });
});

サンドボックス/プロダクションのパリティテスト

最も一般的なAI回帰: プロダクションパスを修正したが、サンドボックスパスを忘れた(またはその逆)。

// サンドボックスのレスポンスが期待される契約と一致することをテスト
describe("GET /api/user/messages(会話リスト)", () => {
  it("サンドボックスモードで partner_name を含む", async () => {
    const req = createTestRequest("/api/user/messages", {
      sandboxUserId: "user-001",
    });
    const res = await GET(req);
    const { json } = await parseResponse(res);

    // これは、partner_name がプロダクションパスに追加されたが
    // サンドボックスパスに追加されなかったバグを捕捉した
    if (json.data.length > 0) {
      for (const conv of json.data) {
        expect("partner_name" in conv).toBe(true);
      }
    }
  });
});

バグチェックワークフローへのテスト統合

カスタムコマンド定義

<!-- .claude/commands/bug-check.md -->
# バグチェック

## ステップ1: 自動テスト(必須、スキップ不可)

コードレビューの前に、最初にこれらのコマンドを実行します:

    npm run test       # Vitestテストスイート
    npm run build      # TypeScript型チェック + ビルド

- テストが失敗した場合 → 最優先バグとして報告
- ビルドが失敗した場合 → 型エラーを最優先で報告
- 両方とも成功した場合のみステップ2に進む

## ステップ2: コードレビュー(AIレビュー)

1. サンドボックス/プロダクションパスの一貫性
2. APIレスポンスの形状がフロントエンドの期待と一致しているか
3. SELECT句の完全性
4. ロールバックを伴うエラーハンドリング
5. 楽観的更新の競合状態

## ステップ3: 修正された各バグに対して、回帰テストを提案する

ワークフロー

ユーザー: "バグチェックして"(または "/bug-check")
  │
  ├─ ステップ1: npm run test
  │   ├─ FAIL → バグを機械的に発見(AIの判断不要)
  │   └─ PASS → 続行
  │
  ├─ ステップ2: npm run build
  │   ├─ FAIL → 型エラーを機械的に発見
  │   └─ PASS → 続行
  │
  ├─ ステップ3: AIコードレビュー(既知の盲点を念頭に)
  │   └─ 結果を報告
  │
  └─ ステップ4: 各修正に対して回帰テストを作成
      └─ 次のバグチェックで修正が壊れている場合に捕捉

一般的なAI回帰パターン

パターン1: サンドボックス/プロダクションパスの不一致

頻度: 最も一般的(4件中3件の回帰で観測)

// 失敗: AIがプロダクションパスにのみフィールドを追加
if (isSandboxMode()) {
  return { data: { id, email, name } };  // 新しいフィールドがない
}
// プロダクションパス
return { data: { id, email, name, notification_settings } };

// 成功: 両方のパスが同じ形状を返さなければならない
if (isSandboxMode()) {
  return { data: { id, email, name, notification_settings: null } };
}
return { data: { id, email, name, notification_settings } };

捕捉するテスト:

it("サンドボックスとプロダクションが同じフィールドを返す", async () => {
  // テスト環境では、サンドボックスモードが強制ON
  const res = await GET(createTestRequest("/api/user/profile"));
  const { json } = await parseResponse(res);

  for (const field of REQUIRED_FIELDS) {
    expect(json.data).toHaveProperty(field);
  }
});

パターン2: SELECT句の欠落

頻度: Supabase/Prismaで新しいカラムを追加する場合によくある

// 失敗: 新しいカラムがレスポンスに追加されたがSELECTにはない
const { data } = await supabase
  .from("users")
  .select("id, email, name")  // notification_settings がない
  .single();

return { data: { ...data, notification_settings: data.notification_settings } };
// → notification_settings は常に undefined

// 成功: SELECT * を使用するか、新しいカラムを明示的に含める
const { data } = await supabase
  .from("users")
  .select("*")
  .single();

パターン3: エラー状態のリーク

頻度: 中程度 — 既存のコンポーネントにエラーハンドリングを追加する場合

// 失敗: エラー状態は設定されたが、古いデータはクリアされていない
catch (err) {
  setError("読み込みに失敗しました");
  // reservations にはまだ前のタブのデータが表示されている!
}

// 成功: エラー時に関連する状態をクリアする
catch (err) {
  setReservations([]);  // 古いデータをクリア
  setError("読み込みに失敗しました");
}

パターン4: 適切なロールバックのない楽観的更新

// 失敗: 失敗時のロールバックなし
const handleRemove = async (id: string) => {
  setItems(prev => prev.filter(i => i.id !== id));
  await fetch(`/api/items/${id}`, { method: "DELETE" });
  // APIが失敗した場合、UIからはアイテムが消えているがDBには残っている
};

// 成功: 以前の状態をキャプチャし、失敗時にロールバック
const handleRemove = async (id: string) => {
  const prevItems = [...items];
  setItems(prev => prev.filter(i => i.id !== id));
  try {
    const res = await fetch(`/api/items/${id}`, { method: "DELETE" });
    if (!res.ok) throw new Error("APIエラー");
  } catch {
    setItems(prevItems);  // ロールバック
    alert("削除に失敗しました");
  }
};

戦略: バグが見つかった場所をテストする

100%カバレッジを目指さないでください。代わりに:

/api/user/profile でバグ発見 → profile APIのテストを書く
/api/user/messages でバグ発見 → messages APIのテストを書く
/api/user/favorites でバグ発見 → favorites APIのテストを書く
/api/user/notifications でバグなし → テストを書かない(まだ)

これがAI開発で機能する理由:

  1. AIは同じカテゴリの間違いを繰り返し起こす傾向がある
  2. バグは複雑な領域(認証、マルチパスロジック、状態管理)に集中する
  3. 一度テストされれば、その特定の回帰は二度と起こらない
  4. テスト数はバグ修正とともに自然に増加 — 無駄な労力がない

クイックリファレンス

AI回帰パターンテスト戦略優先度
サンドボックス/プロダクションの不一致サンドボックスモードで同じレスポンス形状をアサート高
SELECT句の欠落レスポンス内のすべての必須フィールドをアサート高
エラー状態のリークエラー時の状態クリーンアップをアサート中
ロールバックの欠如API障害時の状態復元をアサート中
型キャストによるnullの隠蔽フィールドがundefinedでないことをアサート中

やること / やってはいけないこと

やること:

  • バグを見つけたらすぐにテストを作成する(可能であれば修正する前に)
  • 実装ではなくAPIレスポンスの形状をテストする
  • すべてのバグチェックの最初のステップとしてテストを実行する
  • テストを高速に保つ(サンドボックスモードで合計1秒未満)
  • テスト名は防止するバグにちなんで付ける(例: "BUG-R1 regression")

やってはいけないこと:

  • 一度もバグが発生したことのないコードに対してテストを作成する
  • AIの自己レビューを自動テストの代替として信頼する
  • 「単なるモックデータだから」とサンドボックスパスのテストをスキップする
  • ユニットテストで十分な場合に統合テストを作成する
  • カバレッジ率を目指す — 回帰防止を目指す

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

関連スキル