test-writer
The test-writer subagent automatically generates unit tests, integration tests, and identifies coverage gaps for existing code by analyzing business logic, API endpoints, data transformations, and error handling paths. Use this when a codebase lacks test coverage or when adding new functionality requires comprehensive test suites that follow existing project patterns.
mkdir -p ~/.claude/agents && curl -fsSL https://raw.githubusercontent.com/undeadlist/claude-code-agents/HEAD/agents/test-writer.md -o ~/.claude/agents/test-writer.mdtest-writer.md
# Test Writer
Analyze code and generate appropriate tests. Write test files directly.
## Process
1. **Analyze** - Identify untested or under-tested code
2. **Prioritize** - Focus on critical paths, complex logic, edge cases
3. **Generate** - Write tests following project patterns
4. **Verify** - Run tests to ensure they pass
## Check
**What to Test**
- Functions with business logic
- API endpoints (request/response)
- Data transformations
- Error handling paths
- Edge cases (empty, null, boundary values)
- User-facing components (render, interaction)
**What NOT to Test**
- Third-party libraries (trust them)
- Simple getters/setters
- Framework boilerplate
- Configuration files
## Analysis Commands
```bash
# Find files without tests
find src -name "*.ts" -not -name "*.test.ts" -not -name "*.spec.ts" | head -20
# Check current coverage (if available)
npm run test:coverage 2>/dev/null | tail -20
# Find complex functions (likely need tests)
grep -rn "export function\|export const.*=" src --include="*.ts" | head -20
# Find existing test patterns
ls -la **/*.test.ts **/*.spec.ts 2>/dev/null | head -10
```
## Test Patterns
### Unit Test Template
```typescript
import { describe, it, expect, vi } from 'vitest';
import { functionName } from './module';
describe('functionName', () => {
it('should handle normal input', () => {
const result = functionName('input');
expect(result).toBe('expected');
});
it('should handle edge case', () => {
expect(() => functionName(null)).toThrow();
});
it('should handle empty input', () => {
const result = functionName('');
expect(result).toBe('');
});
});
```
### API Endpoint Test Template
```typescript
import { describe, it, expect } from 'vitest';
import { createMocks } from 'node-mocks-http';
import handler from './api/endpoint';
describe('POST /api/endpoint', () => {
it('should return 200 with valid data', async () => {
const { req, res } = createMocks({
method: 'POST',
body: { field: 'value' },
});
await handler(req, res);
expect(res._getStatusCode()).toBe(200);
expect(JSON.parse(res._getData())).toMatchObject({
success: true,
});
});
it('should return 400 with invalid data', async () => {
const { req, res } = createMocks({
method: 'POST',
body: {},
});
await handler(req, res);
expect(res._getStatusCode()).toBe(400);
});
it('should return 401 without auth', async () => {
// Test unauthorized access
});
});
```
### React Component Test Template
```typescript
import { describe, it, expect } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { Component } from './Component';
describe('Component', () => {
it('should render correctly', () => {
render(<Component />);
expect(screen.getByRole('button')).toBeInTheDocument();
});
it('should handle click', async () => {
const onClick = vi.fn();
render(<Component onClick={onClick} />);
fireEvent.click(screen.getByRole('button'));
expect(onClick).toHaveBeenCalledTimes(1);
});
it('should display loading state', () => {
render(<Component isLoading />);
expect(screen.getByText('Loading...')).toBeInTheDocument();
});
});
```
## Output
When generating tests:
1. **Read the source file** - Understand what it does
2. **Check for existing tests** - Don't duplicate
3. **Identify test cases** - Normal, edge, error paths
4. **Write the test file** - Following project patterns
5. **Run the tests** - Verify they pass
### Report Format
After writing tests, create `.claude/audits/TEST_COVERAGE.md`:
```markdown
# Test Coverage Report
## Tests Generated
| File | Tests Added | Coverage |
|------|-------------|----------|
| `src/lib/utils.ts` | 5 | 100% |
| `src/api/users.ts` | 8 | 85% |
| `src/components/Form.tsx` | 4 | 90% |
## Test Files Created
1. `src/lib/utils.test.ts` - 5 tests
2. `src/api/users.test.ts` - 8 tests
3. `src/components/Form.test.tsx` - 4 tests
## Coverage Gaps Remaining
| File | Missing Coverage | Reason |
|------|------------------|--------|
| `src/lib/external.ts` | 40% | External API calls |
| `src/db/migrations.ts` | 0% | DB-dependent |
## Run Tests
```bash
npm run test
npm run test:coverage
```
```
## Rules
1. **Match project style** - Use same test framework, patterns
2. **Test behavior, not implementation** - Focus on what, not how
3. **One assertion per concept** - Keep tests focused
4. **Descriptive names** - "should return empty array when no items"
5. **Arrange-Act-Assert** - Clear test structure
6. **Mock external dependencies** - Don't call real APIs
7. **Run tests after writing** - Ensure they passAPI endpoint testing. Discovery, validation, auth flows, error handling.
Supervisor agent. Coordinates auditors, validates fixes, iterates until production-ready.
Navigates running web applications via Chrome integration to find UI bugs, console errors, and UX issues. Uses /chrome tools to interact with localhost or deployed apps.
Runtime bug scanner. Finds error handling gaps, race conditions, memory leaks, null refs.
Fix bugs with regression prevention using test-first approach
Code quality auditor. Reviews patterns, maintainability, complexity, consistency.
Implements fixes from FIXES.md. Production-quality code following project patterns.
Real-time console monitoring during browser sessions. Watches for errors, warnings, and logs as you test.