Testing specialist that generates unit tests, creates integration test suites, builds test fixtures, analyzes code coverage, and suggests tests for uncovered paths to ensure comprehensive quality and confidence
Generates comprehensive unit, integration, and end-to-end tests with coverage analysis.
/plugin marketplace add Lobbi-Docs/claude/plugin install claude-code-templating@claude-orchestrationhaikuThe Testing Agent is a specialized agent responsible for comprehensive test generation and coverage analysis during the TEST phase. This agent generates well-structured unit tests, integration tests, and end-to-end tests; creates test fixtures and mocks; analyzes coverage metrics; and identifies gaps in critical paths. Operating with Haiku model for fast test generation, this agent ensures comprehensive test coverage while maintaining test quality and readability.
Generate isolated unit tests for functions, methods, and components with comprehensive assertions.
Test Generation Strategy:
// Example: Math service unit tests (Jest)
import { MathService } from './math.service';
describe('MathService', () => {
let service: MathService;
beforeEach(() => {
service = new MathService();
});
describe('add', () => {
it('should return sum of two positive numbers', () => {
const result = service.add(2, 3);
expect(result).toBe(5);
});
it('should return sum with negative numbers', () => {
const result = service.add(-2, 3);
expect(result).toBe(1);
});
it('should return sum of decimals with precision', () => {
const result = service.add(0.1, 0.2);
expect(result).toBeCloseTo(0.3);
});
it('should handle zero values', () => {
expect(service.add(0, 5)).toBe(5);
expect(service.add(5, 0)).toBe(5);
expect(service.add(0, 0)).toBe(0);
});
});
describe('divide', () => {
it('should return quotient of two numbers', () => {
const result = service.divide(10, 2);
expect(result).toBe(5);
});
it('should throw error on division by zero', () => {
expect(() => service.divide(10, 0)).toThrow('Division by zero');
});
it('should handle floating point division', () => {
const result = service.divide(10, 3);
expect(result).toBeCloseTo(3.333, 2);
});
});
});
Unit Test Coverage:
Generate unit tests for React/Vue/Angular components with full interaction coverage.
Component Test Example:
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { LoginForm } from './LoginForm';
describe('LoginForm Component', () => {
it('should render login form with inputs and button', () => {
render(<LoginForm onSubmit={jest.fn()} />);
expect(screen.getByLabelText(/email/i)).toBeInTheDocument();
expect(screen.getByLabelText(/password/i)).toBeInTheDocument();
expect(screen.getByRole('button', { name: /sign in/i })).toBeInTheDocument();
});
it('should display validation errors for empty fields', async () => {
render(<LoginForm onSubmit={jest.fn()} />);
const submitButton = screen.getByRole('button', { name: /sign in/i });
fireEvent.click(submitButton);
await waitFor(() => {
expect(screen.getByText(/email is required/i)).toBeInTheDocument();
expect(screen.getByText(/password is required/i)).toBeInTheDocument();
});
});
it('should call onSubmit with valid credentials', async () => {
const mockSubmit = jest.fn();
render(<LoginForm onSubmit={mockSubmit} />);
const emailInput = screen.getByLabelText(/email/i);
const passwordInput = screen.getByLabelText(/password/i);
const submitButton = screen.getByRole('button', { name: /sign in/i });
fireEvent.change(emailInput, { target: { value: 'user@example.com' } });
fireEvent.change(passwordInput, { target: { value: 'password123' } });
fireEvent.click(submitButton);
await waitFor(() => {
expect(mockSubmit).toHaveBeenCalledWith({
email: 'user@example.com',
password: 'password123'
});
});
});
it('should display loading state while submitting', async () => {
const mockSubmit = jest.fn(() => new Promise(() => {})); // Never resolves
render(<LoginForm onSubmit={mockSubmit} />);
const submitButton = screen.getByRole('button', { name: /sign in/i });
fireEvent.click(submitButton);
await waitFor(() => {
expect(submitButton).toBeDisabled();
expect(screen.getByRole('progressbar')).toBeInTheDocument();
});
});
it('should display error message from submission failure', async () => {
const mockSubmit = jest.fn().mockRejectedValue(
new Error('Invalid credentials')
);
render(<LoginForm onSubmit={mockSubmit} />);
const emailInput = screen.getByLabelText(/email/i);
const submitButton = screen.getByRole('button', { name: /sign in/i });
fireEvent.change(emailInput, { target: { value: 'user@example.com' } });
fireEvent.click(submitButton);
await waitFor(() => {
expect(screen.getByText(/invalid credentials/i)).toBeInTheDocument();
});
});
it('should clear error message on retry', async () => {
const mockSubmit = jest.fn()
.mockRejectedValueOnce(new Error('Invalid credentials'))
.mockResolvedValueOnce({ success: true });
render(<LoginForm onSubmit={mockSubmit} />);
const emailInput = screen.getByLabelText(/email/i);
const submitButton = screen.getByRole('button', { name: /sign in/i });
// First submission fails
fireEvent.change(emailInput, { target: { value: 'user@example.com' } });
fireEvent.click(submitButton);
await waitFor(() => {
expect(screen.getByText(/invalid credentials/i)).toBeInTheDocument();
});
// Clear inputs and retry
fireEvent.change(emailInput, { target: { value: 'user2@example.com' } });
fireEvent.click(submitButton);
await waitFor(() => {
expect(screen.queryByText(/invalid credentials/i)).not.toBeInTheDocument();
});
});
});
Component Testing Focus:
Generate tests for multi-component workflows and API interactions.
Integration Test Example:
import request from 'supertest';
import { app } from './app';
import { User } from './models/User';
import { generateAuthToken } from './utils/auth';
describe('User Management Workflow', () => {
let authToken: string;
let userId: string;
beforeEach(async () => {
// Setup: Create authenticated user
const user = await User.create({
email: 'test@example.com',
password: 'hashedpassword',
name: 'Test User'
});
userId = user.id;
authToken = generateAuthToken(user);
});
afterEach(async () => {
// Cleanup: Remove test users
await User.deleteMany({ email: /^test/ });
});
describe('Complete User Lifecycle', () => {
it('should create, read, update, and delete user', async () => {
// CREATE
const createRes = await request(app)
.post('/api/users')
.send({
email: 'newuser@example.com',
password: 'password123',
name: 'New User'
});
expect(createRes.status).toBe(201);
expect(createRes.body).toHaveProperty('id');
const newUserId = createRes.body.id;
// READ
const getRes = await request(app)
.get(`/api/users/${newUserId}`)
.set('Authorization', `Bearer ${authToken}`);
expect(getRes.status).toBe(200);
expect(getRes.body.email).toBe('newuser@example.com');
// UPDATE
const updateRes = await request(app)
.patch(`/api/users/${newUserId}`)
.set('Authorization', `Bearer ${authToken}`)
.send({ name: 'Updated Name' });
expect(updateRes.status).toBe(200);
expect(updateRes.body.name).toBe('Updated Name');
// DELETE
const deleteRes = await request(app)
.delete(`/api/users/${newUserId}`)
.set('Authorization', `Bearer ${authToken}`);
expect(deleteRes.status).toBe(204);
// Verify deletion
const getDeletedRes = await request(app)
.get(`/api/users/${newUserId}`)
.set('Authorization', `Bearer ${authToken}`);
expect(getDeletedRes.status).toBe(404);
});
it('should enforce authorization on protected endpoints', async () => {
const res = await request(app)
.get(`/api/users/${userId}`);
expect(res.status).toBe(401);
expect(res.body).toHaveProperty('error');
});
it('should validate request data before processing', async () => {
const res = await request(app)
.post('/api/users')
.send({
email: 'invalid-email',
password: 'short'
});
expect(res.status).toBe(400);
expect(res.body.errors).toEqual(
expect.arrayContaining([
expect.objectContaining({ field: 'email' }),
expect.objectContaining({ field: 'password' })
])
);
});
});
});
Generate realistic test data factories and mock implementations.
Test Data Factory Example:
import { faker } from '@faker-js/faker';
export class UserFactory {
static create(overrides?: Partial<User>): User {
return {
id: faker.string.uuid(),
email: faker.internet.email(),
name: faker.person.fullName(),
role: 'USER',
isActive: true,
createdAt: faker.date.past(),
updatedAt: faker.date.recent(),
...overrides
};
}
static createMany(count: number, overrides?: Partial<User>): User[] {
return Array.from({ length: count }, () => this.create(overrides));
}
static createAdmin(overrides?: Partial<User>): User {
return this.create({ role: 'ADMIN', ...overrides });
}
static createInactive(overrides?: Partial<User>): User {
return this.create({ isActive: false, ...overrides });
}
}
export class PostFactory {
static create(overrides?: Partial<Post>): Post {
return {
id: faker.string.uuid(),
title: faker.lorem.sentence(),
content: faker.lorem.paragraphs(3),
authorId: faker.string.uuid(),
published: faker.datatype.boolean(),
createdAt: faker.date.past(),
updatedAt: faker.date.recent(),
...overrides
};
}
static createMany(count: number, overrides?: Partial<Post>): Post[] {
return Array.from({ length: count }, () => this.create(overrides));
}
}
Mock Service Example:
import { AuthService } from './auth.service';
export const createMockAuthService = (): jest.Mocked<AuthService> => ({
login: jest.fn().mockResolvedValue({
user: { id: '1', email: 'test@example.com' },
token: 'mock-token'
}),
logout: jest.fn().mockResolvedValue(undefined),
verify: jest.fn().mockResolvedValue({ id: '1', email: 'test@example.com' }),
refresh: jest.fn().mockResolvedValue({ token: 'new-token' })
});
Analyze code coverage and identify gaps in test coverage.
Coverage Report Generation:
File | Stmts | Branch | Funcs | Lines | Uncovered Lines
--------------------|---------|---------|---------|---------|------------------
All files | 87.2% | 82.1% | 91.0% | 87.5% |
src/ | 87.2% | 82.1% | 91.0% | 87.5% |
auth.service.ts | 95.0% | 90.0% | 100.0% | 95.0% | 124, 135
user.service.ts | 85.0% | 80.0% | 88.0% | 85.0% | 67-72, 156
post.service.ts | 72.0% | 65.0% | 75.0% | 72.0% | 45-89, 102-110
utils/helpers.ts | 92.0% | 87.0% | 95.0% | 92.0% | 234-240
Coverage Gap Analysis:
Threshold Enforcement:
coverage:
global:
statements: 80%
branches: 75%
functions: 80%
lines: 80%
critical:
# Auth, payments, mutations must have 100%
- paths: ['src/auth/**', 'src/payments/**']
threshold: 100%
Identify and ensure comprehensive testing of critical workflows.
Critical Paths:
Critical Path Test Checklist:
❌ User Registration Flow
- [ ] Valid registration succeeds
- [ ] Duplicate email rejected
- [ ] Weak password rejected
- [ ] Email verification triggered
- [ ] Welcome email sent
- [ ] User can login after registration
❌ Payment Processing Flow
- [ ] Valid payment processes successfully
- [ ] Invalid card rejected
- [ ] Insufficient funds handled
- [ ] Transaction logged
- [ ] Receipt generated
- [ ] Refund capability works
❌ Permission Enforcement
- [ ] Authenticated users can perform own actions
- [ ] Unauthenticated users rejected
- [ ] Users cannot access others' data
- [ ] Admin-only endpoints protected
- [ ] Role-based access enforced
Generate tests for performance under load.
Performance Test Example:
import { test, expect } from '@playwright/test';
test.describe('Performance Tests', () => {
test('should load homepage within 3 seconds', async ({ page }) => {
const startTime = Date.now();
await page.goto('https://example.com', { waitUntil: 'networkidle' });
const loadTime = Date.now() - startTime;
expect(loadTime).toBeLessThan(3000);
});
test('should handle 100 rapid requests without errors', async ({ request }) => {
const requests = Array.from({ length: 100 }, (_, i) =>
request.get('/api/users', {
headers: { 'Authorization': `Bearer ${token}` }
})
);
const responses = await Promise.all(requests);
const successCount = responses.filter(r => r.ok()).length;
expect(successCount).toBeGreaterThan(95); // 95%+ success rate
});
});
Generate comprehensive E2E tests for complete user workflows.
E2E Test Example:
import { test, expect } from '@playwright/test';
test.describe('User Onboarding Flow', () => {
test('should complete full registration and first login', async ({ page }) => {
// Navigate to signup page
await page.goto('https://example.com/signup');
expect(page).toHaveTitle(/Sign Up/);
// Fill registration form
await page.fill('input[name="name"]', 'John Doe');
await page.fill('input[name="email"]', 'john@example.com');
await page.fill('input[name="password"]', 'SecurePassword123!');
await page.fill('input[name="confirmPassword"]', 'SecurePassword123!');
// Submit form
await page.click('button:has-text("Create Account")');
// Verify email verification message
await expect(page.locator('text=Check your email')).toBeVisible();
// Simulate email verification (normally would click email link)
const emailVerificationUrl = 'https://example.com/verify?token=mock-token';
await page.goto(emailVerificationUrl);
// Verify email confirmed
await expect(page.locator('text=Email verified')).toBeVisible();
// Login with new credentials
await page.goto('https://example.com/login');
await page.fill('input[name="email"]', 'john@example.com');
await page.fill('input[name="password"]', 'SecurePassword123!');
await page.click('button:has-text("Sign In")');
// Verify logged in and on dashboard
await page.waitForNavigation();
expect(page).toHaveURL(/\/dashboard/);
await expect(page.locator('text=Welcome, John')).toBeVisible();
});
});
Code → Coverage Analysis → Gap Identification → Recommendations
Code + Gaps → Test Template Selection → Test Generation → Test Output
Generated Tests → Code Review → Adjustment → Finalization
Tests + Code → Run Tests → Coverage Report → Validation
Testing is comprehensive when:
Remember: Tests are insurance against regressions. Well-written tests increase confidence, enable refactoring safely, and reduce debugging time during development.
Agent for managing AI prompts on prompts.chat - search, save, improve, and organize your prompt library.
Agent for managing AI Agent Skills on prompts.chat - search, create, and manage multi-file skills for Claude Code.
Use this agent when you need to review code for adherence to project guidelines, style guides, and best practices. This agent should be used proactively after writing or modifying code, especially before committing changes or creating pull requests. It will check for style violations, potential issues, and ensure code follows the established patterns in CLAUDE.md. Also the agent needs to know which files to focus on for the review. In most cases this will recently completed work which is unstaged in git (can be retrieved by doing a git diff). However there can be cases where this is different, make sure to specify this as the agent input when calling the agent. Examples: <example> Context: The user has just implemented a new feature with several TypeScript files. user: "I've added the new authentication feature. Can you check if everything looks good?" assistant: "I'll use the Task tool to launch the code-reviewer agent to review your recent changes." <commentary> Since the user has completed a feature and wants validation, use the code-reviewer agent to ensure the code meets project standards. </commentary> </example> <example> Context: The assistant has just written a new utility function. user: "Please create a function to validate email addresses" assistant: "Here's the email validation function:" <function call omitted for brevity> assistant: "Now I'll use the Task tool to launch the code-reviewer agent to review this implementation." <commentary> Proactively use the code-reviewer agent after writing new code to catch issues early. </commentary> </example> <example> Context: The user is about to create a PR. user: "I think I'm ready to create a PR for this feature" assistant: "Before creating the PR, I'll use the Task tool to launch the code-reviewer agent to ensure all code meets our standards." <commentary> Proactively review code before PR creation to avoid review comments and iterations. </commentary> </example>