AI Regression Testing
Устраните слепые зоны AI-кодинга с помощью автоматизированных стратегий регрессионного тестирования, шаблонов sandbox API и рабочих процессов проверки ошибок для Claude Code и Cursor.
Этот скилл предоставляет специализированные шаблоны тестирования, разработанные специально для сред разработки с ИИ-ассистентами, таких как Claude Code или Cursor. Он решает проблему «слепого пятна саморецензии» — когда ИИ-модель пропускает ошибки в собственном коде при ревью — за счет применения sandbox-режима тестирования API, обеспечения паритета между продакшеном и mock-средами, а также автоматизации рабочих процессов. Фокус на проверке формы ответа и типичных ошибках ИИ (например, пропуск SELECT-выражений или утечка состояния) позволяет разработчикам создавать надежные приложения без необходимости использования тяжелых зависимостей БД на этапе разработки.
Ключевые возможности
Сценарии использования
| name | ai-regression-testing |
|---|---|
| description | Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. |
| origin | ECC |
Testing patterns specifically designed for AI-assisted development, where the same model writes code and reviews it — creating systematic blind spots that only automated tests can catch.
- AI agent (Claude Code, Cursor, Codex) has modified API routes or backend logic
- A bug was found and fixed — need to prevent re-introduction
- Project has a sandbox/mock mode that can be leveraged for DB-free testing
- Running
/bug-checkor similar review commands after code changes - Multiple code paths exist (sandbox vs production, feature flags, etc.)
When an AI writes code and then reviews its own work, it carries the same assumptions into both steps. This creates a predictable failure pattern:
AI writes fix → AI reviews fix → AI says "looks correct" → Bug still exists
Real-world example (observed in production):
Fix 1: Added notification_settings to API response
→ Forgot to add it to the SELECT query
→ AI reviewed and missed it (same blind spot)
Fix 2: Added it to SELECT query
→ TypeScript build error (column not in generated types)
→ AI reviewed Fix 1 but didn't catch the SELECT issue
Fix 3: Changed to SELECT *
→ Fixed production path, forgot sandbox path
→ AI reviewed and missed it AGAIN (4th occurrence)
Fix 4: Test caught it instantly on first run PASS:
The pattern: sandbox/production path inconsistency is the #1 AI-introduced regression.
Most projects with AI-friendly architecture have a sandbox/mock mode. This is the key to fast, DB-free API testing.
// 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
// Force sandbox mode — no database needed
process.env.SANDBOX_MODE = "true";
process.env.NEXT_PUBLIC_SUPABASE_URL = "";
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY = "";// __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 };
}The key principle: write tests for bugs that were found, not for code that works.
// __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";
// Define the contract — what fields MUST be in the response
const REQUIRED_FIELDS = [
"id",
"email",
"full_name",
"phone",
"role",
"created_at",
"avatar_url",
"notification_settings", // ← Added after bug found it missing
];
describe("GET /api/user/profile", () => {
it("returns all required fields", 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);
}
});
// Regression test — this exact bug was introduced by AI 4 times
it("notification_settings is not undefined (BUG-R1 regression)", 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);
});
});The most common AI regression: fixing production path but forgetting sandbox path (or vice versa).
// Test that sandbox responses match the expected contract
describe("GET /api/user/messages (conversation list)", () => {
it("includes partner_name in sandbox mode", async () => {
const req = createTestRequest("/api/user/messages", {
sandboxUserId: "user-001",
});
const res = await GET(req);
const { json } = await parseResponse(res);
// This caught a bug where partner_name was added
// to production path but not sandbox path
if (json.data.length > 0) {
for (const conv of json.data) {
expect("partner_name" in conv).toBe(true);
}
}
});
});<!-- .claude/commands/bug-check.md -->
# Bug Check
## Step 1: Automated Tests (mandatory, cannot skip)
Run these commands FIRST before any code review:
npm run test # Vitest test suite
npm run build # TypeScript type check + build
- If tests fail → report as highest priority bug
- If build fails → report type errors as highest priority
- Only proceed to Step 2 if both pass
## Step 2: Code Review (AI review)
1. Sandbox / production path consistency
2. API response shape matches frontend expectations
3. SELECT clause completeness
4. Error handling with rollback
5. Optimistic update race conditions
## Step 3: For each bug fixed, propose a regression testUser: "バグチェックして" (or "/bug-check")
│
├─ Step 1: npm run test
│ ├─ FAIL → Bug found mechanically (no AI judgment needed)
│ └─ PASS → Continue
│
├─ Step 2: npm run build
│ ├─ FAIL → Type error found mechanically
│ └─ PASS → Continue
│
├─ Step 3: AI code review (with known blind spots in mind)
│ └─ Findings reported
│
└─ Step 4: For each fix, write a regression test
└─ Next bug-check catches if fix breaks
Frequency: Most common (observed in 3 out of 4 regressions)
// FAIL: AI adds field to production path only
if (isSandboxMode()) {
return { data: { id, email, name } }; // Missing new field
}
// Production path
return { data: { id, email, name, notification_settings } };
// PASS: Both paths must return the same shape
if (isSandboxMode()) {
return { data: { id, email, name, notification_settings: null } };
}
return { data: { id, email, name, notification_settings } };Test to catch it:
it("sandbox and production return same fields", async () => {
// In test env, sandbox mode is forced 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);
}
});Frequency: Common with Supabase/Prisma when adding new columns
// FAIL: New column added to response but not to SELECT
const { data } = await supabase
.from("users")
.select("id, email, name") // notification_settings not here
.single();
return { data: { ...data, notification_settings: data.notification_settings } };
// → notification_settings is always undefined
// PASS: Use SELECT * or explicitly include new columns
const { data } = await supabase
.from("users")
.select("*")
.single();Frequency: Moderate — when adding error handling to existing components
// FAIL: Error state set but old data not cleared
catch (err) {
setError("Failed to load");
// reservations still shows data from previous tab!
}
// PASS: Clear related state on error
catch (err) {
setReservations([]); // Clear stale data
setError("Failed to load");
}// FAIL: No rollback on failure
const handleRemove = async (id: string) => {
setItems(prev => prev.filter(i => i.id !== id));
await fetch(`/api/items/${id}`, { method: "DELETE" });
// If API fails, item is gone from UI but still in DB
};
// PASS: Capture previous state and rollback on failure
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 error");
} catch {
setItems(prevItems); // Rollback
alert("削除に失敗しました");
}
};Don't aim for 100% coverage. Instead:
Bug found in /api/user/profile → Write test for profile API
Bug found in /api/user/messages → Write test for messages API
Bug found in /api/user/favorites → Write test for favorites API
No bug in /api/user/notifications → Don't write test (yet)
Why this works with AI development:
- AI tends to make the same category of mistake repeatedly
- Bugs cluster in complex areas (auth, multi-path logic, state management)
- Once tested, that exact regression cannot happen again
- Test count grows organically with bug fixes — no wasted effort
| AI Regression Pattern | Test Strategy | Priority |
|---|---|---|
| Sandbox/production mismatch | Assert same response shape in sandbox mode | High |
| SELECT clause omission | Assert all required fields in response | High |
| Error state leakage | Assert state cleanup on error | Medium |
| Missing rollback | Assert state restored on API failure | Medium |
| Type cast masking null | Assert field is not undefined | Medium |
DO:
- Write tests immediately after finding a bug (before fixing it if possible)
- Test the API response shape, not the implementation
- Run tests as the first step of every bug-check
- Keep tests fast (< 1 second total with sandbox mode)
- Name tests after the bug they prevent (e.g., "BUG-R1 regression")
DON'T:
- Write tests for code that has never had a bug
- Trust AI self-review as a substitute for automated tests
- Skip sandbox path testing because "it's just mock data"
- Write integration tests when unit tests suffice
- Aim for coverage percentage — aim for regression prevention
🧪 Что это
Навык AI Regression Testing — это набор стратегий и шаблонов для автоматизированного регрессионного тестирования проектов, которые активно используют AI-ассистентов (Claude, Cursor, Codex) для написания и ревью кода.
Главная цель — выявить и предотвратить систематические слепые зоны, возникающие, когда одна и та же модель пишет код, а затем его рецензирует. Это не замена обычным тестам, а целенаправленная работа с регрессиями, которые AI наиболее часто пропускает.
⚙️ Как работает
🧠 Основная проблема: AI не видит своих ошибок
Когда AI пишет код и сам же его проверяет, он проносит одни и те же предположения через оба этапа. Это приводит к предсказуемому циклу:
AI пишет исправление → AI проверяет исправление → AI говорит «всё верно» → Баг остался
Реальный пример из документации: баг с полем notification_settings исправлялся 3 раза разными способами, и все 3 раза AI-ревью его пропустило. Только автоматический тест поймал проблему с первого запуска.
📋 Типичные сценарии использования
- AI-агент изменил API-роуты или логику бэкенда
- Найден и исправлен баг — нужно убедиться, что он не вернётся
- В проекте есть песочница (sandbox/mock mode), которую можно использовать для тестов без БД
- Запуск команд
/bug-checkили аналогичных после изменений - В проекте есть несколько путей исполнения (sandbox vs production, feature flags)
🏗️ Архитектура тестов
Ключевая идея — тесты должны быть быстрыми и не требовать базы данных. Для этого используется sandbox-режим, который обычно уже есть в проектах с AI-архитектурой.
Пример настройки Vitest:
# __tests__/setup.ts
process.env.SANDBOX_MODE = "true";
process.env.NEXT_PUBLIC_SUPABASE_URL = "";
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY = "";
Тогда можно напрямую импортировать API-роуты Next.js и тестировать их, прокидывая фиктивные запросы через утилиту createTestRequest.
🔬 Четыре главных паттерна AI-регрессий
Все наблюдения основаны на реальных данных, паттерны отсортированы по частоте возникновения.
1. 🔴 Несоответствие путей sandbox/production
Это — номер один по частоте (3 из 4 регрессий). AI добавляет новое поле в ответ production-пути, но забывает сделать то же самое для sandbox-пути.
// ОШИБКА: поле notification_settings только в production
if (isSandboxMode()) {
return { data: { id, email, name } }; // Новое поле забыли
}
return { data: { id, email, name, notification_settings } };
Как ловить: тест проверяет, что ответ sandbox содержит все обязательные поля, заданные в контракте (REQUIRED_FIELDS).
2. 🔴 Пропуск поля в SELECT запросе
Часто встречается при работе с Supabase/Prisma. Поле добавили в ответ, но забыли добавить в select().
// ОШИБКА: notification_settings есть в ответе, но не в SELECT
const { data } = await supabase.from("users").select("id, email, name").single();
return { data: { ...data, notification_settings: data.notification_settings } };
// → notification_settings всегда undefined
Как ловить: тест проверяет, что все обязательные поля не только присутствуют в ответе, но и не равны undefined.
3. 🟡 Утечка старого состояния при ошибке
AI может добавить обработку ошибки, но забыть очистить предыдущие данные, которые остаются на экране.
// ОШИБКА: данные не очищены
catch (err) {
setError("Failed to load");
// reservations всё ещё показывают старые данные!
}
4. 🟡 Оптимистичное обновление без отката
При оптимистичном удалении элемента из UI, если API-запрос падает, элемент исчезает навсегда, хотя в базе он остаётся.
// ПРАВИЛЬНО: сохранение состояния для отката
const handleRemove = async (id) => {
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 error");
} catch {
setItems(prevItems); // Откат
}
};
📂 Стратегия: «Тестируй там, где нашли баг»
Не нужно стремиться к 100% покрытию. Вместо этого:
- Баг найден в
/api/user/profile→ пишем тест для profile - Баг найден в
/api/user/messages→ пишем тест для messages - Нет багов в
/api/user/notifications→ тест не пишем (пока)
Это работает, потому что AI склонен повторять однотипные ошибки в сложных участках (авторизация, многопоточная логика, управление состоянием). Как только тест написан — эта регрессия больше не вернётся. Количество тестов растёт органично, без лишних затрат.
📋 Интеграция в /bug-check workflow
Рекомендуемый порядок действий для команды /bug-check:
- Автоматические тесты (
npm run test) — обязательный шаг, пропустить нельзя - TypeScript-проверка (
npm run build) — ловит ошибки типов - AI-ревью кода — фокус на sandbox/production, форму ответа, SELECT-запросы, обработку ошибок
- Для каждого исправления — написать регрессионный тест
✅ DO / ❌ DON'T
DO:
- Пиши тесты сразу после нахождения бага (до исправления, если возможно)
- Тестируй форму ответа API, а не реализацию
- Запускай тесты первым шагом любого баг-чека
- Держи тесты быстрыми (< 1 секунды с sandbox-режимом)
- Называй тесты по имени бага (например,
BUG-R1 regression)
DON'T:
- Не пиши тесты для кода, в котором никогда не было багов
- Не доверяй AI-саморевью как замене автоматическим тестам
- Не пропускай sandbox-тесты, потому что «это просто моковые данные»
- Не ставь интеграционные тесты там, где хватит юнит-тестов
- Не гонись за процентом покрытия — цель в предотвращении регрессий
🎯 Когда использовать
Этот подход максимально эффективен, если:
- AI-агент регулярно модифицирует код бэкенда (роуты, API, логика)
- Вы уже сталкивались с ситуацией «AI написал фикс, AI его проверил, баг остался»
- В проекте есть sandbox-режим, позволяющий тестировать API без базы данных
- У вас есть CI/CD, где можно запускать тесты при каждом пулл-реквесте
💡 Важно знать
- Тесты должны быть атомарными и быстрыми. Если тест зависит от БД или внешнего сервиса — он перестаёт быть регрессионным в контексте AI, потому что его сложно запустить сразу после генерации кода.
- Не полагайся на эвристику. Тест проверяет конкретное поле или состояние, а не «похоже ли это на типичную ошибку». Это единственный способ гарантированно поймать регрессию.
- Паттерны расширяемы. Если вы заметили новый тип AI-регрессии (например, неправильная работа с пагинацией), просто добавьте его в список и напишите соответствующий тест-шаблон.
Помогает ли этот навык с ошибками типов TypeScript?
Да, интегрированный рабочий процесс включает обязательные этапы сборки и проверки типов для выявления регрессий, которые ИИ может пропустить при обычном ревью кода.
Что такое слепое пятно ИИ в разработке программного обеспечения?
Слепое пятно ИИ возникает, когда одна и та же модель пишет и проверяет код; поскольку она использует одинаковые допущения на обоих этапах, она часто пропускает собственные логические ошибки.
Когда лучше всего запускать автоматизированную проверку ошибок?
Запускать рабочий процесс проверки ошибок следует после каждого значительного изменения кода и перед коммитом, чтобы убедиться, что новые исправления не нарушили существующую функциональность.
Можно ли использовать этот навык с фреймворками, отличными от Next.js?
Да. Хотя приведенные примеры используют Vitest и Next.js, логика проверки формы ответа и сопоставления путей применима к любому современному веб-фреймворку.
Как тестирование в изолированной среде помогает разработке ИИ?
Оно позволяет ИИ быстро запускать тесты без базы данных, используя имитированные окружения, мгновенно выявляя нарушения контрактов API без сложной настройки инфраструктуры.
Синхронизируйте навыки с Claude Cowork, Claude Code, Codex и другими.
Установка одной командой.
npx skillfish add affaan-m/everything-claude-code ai-regression-testingИсточник: https://mcpmarket.com/tools/skills/ai-regression-testing-2
Комментарии
Комментариев пока нет. Будьте первым.