Testing

Test File Generator

Reads source code and generates comprehensive tests covering happy paths, edge cases, and error handling.

SKILL.md

SKILL.md
---
description: Generate comprehensive tests for existing source code
allowed-tools: Read, Bash(ls), Bash(cat *), Write, Glob
---

# Test Writer

Generate a thorough test file for existing source code, covering happy paths, edge cases, and error scenarios.

## Arguments

- `$ARGUMENTS` — path to the source file to test

## Steps

1. Read the source file at `$ARGUMENTS`.
2. Identify all exported functions, classes, and components.
3. For each export, analyze:
   - Input parameters and their types
   - Return types and possible return values
   - Side effects (API calls, DOM manipulation, file I/O)
   - Error conditions and thrown exceptions
   - Edge cases (empty inputs, boundary values, null/undefined)
4. Check for an existing test file and existing test infrastructure:
   - Look for `*.test.*` or `*.spec.*` files nearby
   - Read the project test config (jest.config, vitest.config, etc.)
   - Identify mocking patterns and test utilities in use
5. Generate the test file adjacent to the source file.

## Test categories to include

### Happy path tests
- Test each function with typical, valid inputs.
- Verify return values match expected output.

### Edge cases
- Empty strings, empty arrays, zero, negative numbers.
- Maximum/minimum boundary values.
- Unicode and special characters in string inputs.

### Error handling
- Invalid input types (if not caught by TypeScript at compile time).
- Network failures for async operations (mock rejected promises).
- Timeout scenarios for async code.

### Integration points
- Mock external dependencies (API clients, database, file system).
- Verify mocks are called with expected arguments.
- Test retry logic if present.

## Output format

Use `describe` blocks grouped by function/method name. Use clear test names that describe the behavior, not the implementation:

```typescript
describe('calculateDiscount', () => {
  it('applies percentage discount to the subtotal', () => { ... });
  it('returns zero when discount code is expired', () => { ... });
  it('throws when subtotal is negative', () => { ... });
});
```

## Rules

- Match the project's existing test style and framework.
- Never test private implementation details — only test the public API.
- Each test should be independent and not rely on execution order.
- Use descriptive test names that read as specifications.
- Prefer `toEqual` for objects, `toBe` for primitives, `toThrow` for errors.

How It Works

This skill follows the pattern of reading existing code to understand context, but applies it specifically to testing. By examining nearby test files and the project's test configuration, the agent will produce tests that use the correct framework (Jest, Vitest, Mocha) and follow established mocking patterns.

The categorized approach — happy paths, edge cases, error handling, integration points — ensures comprehensive coverage. Most developers focus heavily on happy paths; this skill forces consideration of boundary conditions and failure modes that often harbor bugs.

The naming convention guidance ("describe the behavior, not the implementation") produces tests that serve as living documentation. When a test fails, names like "returns zero when discount code is expired" immediately communicate what broke, unlike names like "test case 3" or "handles edge case".