From ftitos-claude-code
Regression testing strategies for AI-assisted development. Catch systematic blind spots where the same model writes and reviews code.
npx claudepluginhub nassimbf/ftitos-claude-codeThis skill uses the workspace's default tool permissions.
Testing patterns designed for AI-assisted development, where the same model writes code and reviews it -- creating systematic blind spots that only automated tests can catch.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Share bugs, ideas, or general feedback.
Testing patterns designed for AI-assisted development, where the same model writes code and reviews it -- creating systematic blind spots that only automated tests can catch.
When an AI writes code and then reviews its own work, it carries the same assumptions into both steps:
AI writes fix -> AI reviews fix -> AI says "looks correct" -> Bug still exists
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
}
return { data: { id, email, name, notification_settings } };
// PASS: Both paths return the same shape
if (isSandboxMode()) {
return { data: { id, email, name, notification_settings: null } };
}
return { data: { id, email, name, notification_settings } };
Common when adding new columns:
// FAIL: New column added to response but not to SELECT
const { data } = await db.from("users").select("id, email, name").single();
return { data: { ...data, notification_settings: data.notification_settings } };
// notification_settings is always undefined
// FAIL: Error state set but old data not cleared
catch (err) {
setError("Failed to load");
// items still shows data from previous view
}
// PASS: Clear related state on error
catch (err) {
setItems([]);
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" });
};
// 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);
}
};
Write tests for bugs that were found, not for code that works:
const REQUIRED_FIELDS = [
"id", "email", "full_name", "phone", "role",
"created_at", "avatar_url", "notification_settings",
];
describe("GET /api/user/profile", () => {
it("returns all required fields", async () => {
const res = await GET(createTestRequest("/api/user/profile"));
const { status, json } = await parseResponse(res);
expect(status).toBe(200);
for (const field of REQUIRED_FIELDS) {
expect(json.data).toHaveProperty(field);
}
});
});
1. Run automated tests (npm test)
-> FAIL = Bug found mechanically
-> PASS = Continue
2. Run build check (npm run build)
-> FAIL = Type error found mechanically
-> PASS = Continue
3. AI code review (with known blind spots in mind)
4. For each fix, write a regression test
| AI Regression Pattern | Test Strategy | Priority |
|---|---|---|
| Sandbox/production mismatch | Assert same response shape in all modes | 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 |
DO:
DON'T: