Test Generator
Generate well-structured, maintainable test suites that provide confidence in code correctness. Follow the test pyramid approach: many unit tests, fewer integration tests, minimal E2E tests.
Test Generation Workflow
Step 1: Analyze the Code Under Test
- Read the source file(s) to understand functionality.
- Identify all public functions, methods, and exported interfaces.
- Map code paths — branches, loops, error handlers, early returns.
- Identify external dependencies — APIs, databases, file system, third-party services.
- Note any existing tests to avoid duplication and maintain consistency.
Step 2: Identify Test Cases
For each function or method, identify:
Happy Path Cases
- Standard inputs producing expected outputs.
- Common use cases as described in requirements or documentation.
Edge Cases
- Null/undefined/empty inputs: What happens with no data?
- Boundary values: Minimum, maximum, zero, negative numbers, empty strings, single-character strings.
- Type boundaries: Integer overflow, floating point precision, very long strings.
- Collection edges: Empty array, single element, very large collections.
- Concurrent access: Race conditions, simultaneous modifications.
Error Cases
- Invalid input types or formats.
- Missing required fields.
- External service failures (network errors, timeouts, 5xx responses).
- Permission/authorization failures.
- Resource not found scenarios.
- Data constraint violations (unique, foreign key, validation).
State Transitions
- Before/after states for mutations.
- Idempotency verification — calling twice produces the same result.
- Order-dependent behavior.
Step 3: Write Tests Using AAA Pattern
Every test follows Arrange, Act, Assert:
// Arrange — set up test data, mocks, and preconditions
// Act — execute the function or operation under test
// Assert — verify the outcome matches expectations
Test Structure Rules
- One assertion concept per test — a test should verify one behavior. Multiple
expect calls are fine if they verify the same logical assertion.
- Descriptive test names:
should [expected behavior] when [condition/context]
- No test logic — no conditionals, loops, or try/catch in tests. If you need them, the test is too complex.
- Independent tests — no shared mutable state, no execution order dependencies.
- Fast tests — unit tests should run in milliseconds. Mock external dependencies.
Step 4: Apply Mocking Strategy
When to Mock
- External HTTP APIs and services.
- Database connections and queries.
- File system operations.
- Time-dependent operations (
Date.now(), timers).
- Random number generation.
- Environment variables and configuration.
When NOT to Mock
- The code under test itself.
- Pure utility functions with no side effects.
- Value objects and data structures.
- Simple internal collaborators that are fast and deterministic.
Mock Quality Rules
- Mocks should match the real interface — use type-safe mocks when possible.
- Verify mock interactions only when the interaction IS the behavior (e.g., "sends an email").
- Prefer stubs (return values) over mocks (verify calls) for dependencies that provide data.
- Reset mocks between tests to prevent state leakage.
Step 5: Generate Tests by Type
Unit Tests
- Test individual functions and methods in isolation.
- Mock all external dependencies.
- Focus on logic, calculations, transformations, validations.
- Target: cover all code paths including error branches.
describe('calculateDiscount', () => {
it('should apply 10% discount for orders over $100', () => {
const order = createOrder({ subtotal: 150 });
const result = calculateDiscount(order);
expect(result).toBe(15);
});
it('should return 0 discount for orders under $100', () => {
const order = createOrder({ subtotal: 50 });
const result = calculateDiscount(order);
expect(result).toBe(0);
});
it('should throw when order subtotal is negative', () => {
const order = createOrder({ subtotal: -10 });
expect(() => calculateDiscount(order)).toThrow('Invalid subtotal');
});
});
Integration Tests
- Test interactions between modules or services.
- Use real implementations for internal dependencies, mock external boundaries.
- Verify data flows correctly through the system.
- Test database queries against a test database (not mocked).
describe('UserService.createUser', () => {
it('should create user and send welcome email', async () => {
const emailService = createMockEmailService();
const service = new UserService(testDatabase, emailService);
const user = await service.createUser({ name: 'Jane', email: 'jane@example.com' });
expect(user.id).toBeDefined();
const savedUser = await testDatabase.users.findById(user.id);
expect(savedUser.name).toBe('Jane');
expect(emailService.sendWelcome).toHaveBeenCalledWith('jane@example.com');
});
});
E2E Tests
- Test complete user workflows through the full stack.
- Use real services (or dedicated test instances).
- Focus on critical business paths — registration, checkout, core CRUD operations.
- Keep the number small — these are slow and expensive.
Step 6: Coverage Guidance
| Test Type |
Coverage Target |
Focus |
| Unit |
80%+ line coverage |
Business logic, calculations, validations |
| Integration |
Critical paths covered |
Service interactions, data persistence |
| E2E |
Core workflows covered |
User-facing flows, happy paths |
Coverage is a guide, not a goal. 80% meaningful coverage is better than 100% coverage with trivial assertions. Focus on:
- Code with complex logic or many branches.
- Code that handles money, permissions, or sensitive data.
- Code that has broken before (regression tests).
Skip testing:
- Simple getters/setters with no logic.
- Framework-generated boilerplate.
- Configuration objects with no behavior.
Test File Organization
mobile/src/
services/
user-service.ts
user-service.test.ts # Unit tests colocated
mobile/tests/
integration/
user-service.integration.ts # Integration tests separate
e2e/
user-registration.e2e.ts # E2E tests separate
fixtures/
users.ts # Shared test data factories
helpers/
test-database.ts # Test infrastructure utilities
Deep guides (read on demand, do not preload)
The body is the workflow. The idiom for each target lives in std-testing's references — which
are scoped to **/*.test.* / **/*.spec.* — and they are decision-shaped, with the bad/good
pairs. Read the one matching what you are testing rather than reconstructing it:
- Vitest + RTL setup, which query to reach for, MSW, providers, Zustand, Framer Motion,
ApexCharts →
@skills/std-testing/references/react-components.md
- Next.js Server Components, server actions,
generateMetadata, route handlers →
@skills/std-testing/references/nextjs-server.md
- React Native: RNTL, navigation, Reanimated, MMKV, Centrifugo →
@skills/std-testing/references/react-native.md
- Unit vs integration, mock boundaries, test data builders, the edge-case matrix, Sidekiq
jobs →
@skills/std-testing/references/test-strategy.md
- Naming, the AAA structure, fixtures, mock/stub/spy guidance, test data, CI integration →
references/testing-standards.md
This body carried its own copy of the web-frontend material until it drifted from the owner. The
copy compressed RTL's query priority to one line — getByRole > getByLabelText > getByText > getByTestId — which drops getByPlaceholderText and, more importantly, the reason: a
getByTestId test passes even when the "button" is a non-focusable <div> with no accessible
name, so it cannot detect the accessibility regression it was supposed to catch. A summary of a
decision guide is not a smaller version of it; it is the part that does not tell you why.
Output
When generating tests, provide:
- The complete test file(s) with all test cases.
- Any required test fixtures or factories.
- A brief summary of what is covered and any known gaps.
- Setup instructions if new test infrastructure is needed.
1---2name: test-generator3description: Generate comprehensive test suites including unit, integration, and E2E tests following AAA pattern. Use this skill whenever someone asks to write tests, generate specs, improve coverage, add test cases, or says things like "write tests for this", "add test coverage", "generate specs", "I need tests for X", "create a test suite", or "help me test this function". Also trigger when someone mentions flaky test investigation, test infrastructure setup, or mock strategy questions.4agent: test-generator5context: fork6argument-hint: "file path or module name"7model: sonnet8---910# Test Generator1112Generate well-structured, maintainable test suites that provide confidence in code correctness. Follow the test pyramid approach: many unit tests, fewer integration tests, minimal E2E tests.1314## Test Generation Workflow1516### Step 1: Analyze the Code Under Test17181. Read the source file(s) to understand functionality.192. Identify all public functions, methods, and exported interfaces.203. Map code paths — branches, loops, error handlers, early returns.214. Identify external dependencies — APIs, databases, file system, third-party services.225. Note any existing tests to avoid duplication and maintain consistency.2324### Step 2: Identify Test Cases2526For each function or method, identify:2728#### Happy Path Cases29- Standard inputs producing expected outputs.30- Common use cases as described in requirements or documentation.3132#### Edge Cases33- **Null/undefined/empty inputs**: What happens with no data?34- **Boundary values**: Minimum, maximum, zero, negative numbers, empty strings, single-character strings.35- **Type boundaries**: Integer overflow, floating point precision, very long strings.36- **Collection edges**: Empty array, single element, very large collections.37- **Concurrent access**: Race conditions, simultaneous modifications.3839#### Error Cases40- Invalid input types or formats.41- Missing required fields.42- External service failures (network errors, timeouts, 5xx responses).43- Permission/authorization failures.44- Resource not found scenarios.45- Data constraint violations (unique, foreign key, validation).4647#### State Transitions48- Before/after states for mutations.49- Idempotency verification — calling twice produces the same result.50- Order-dependent behavior.5152### Step 3: Write Tests Using AAA Pattern5354Every test follows **Arrange, Act, Assert**:5556```57// Arrange — set up test data, mocks, and preconditions58// Act — execute the function or operation under test59// Assert — verify the outcome matches expectations60```6162#### Test Structure Rules63641. **One assertion concept per test** — a test should verify one behavior. Multiple `expect` calls are fine if they verify the same logical assertion.652. **Descriptive test names**: `should [expected behavior] when [condition/context]`663. **No test logic** — no conditionals, loops, or try/catch in tests. If you need them, the test is too complex.674. **Independent tests** — no shared mutable state, no execution order dependencies.685. **Fast tests** — unit tests should run in milliseconds. Mock external dependencies.6970### Step 4: Apply Mocking Strategy7172#### When to Mock73- External HTTP APIs and services.74- Database connections and queries.75- File system operations.76- Time-dependent operations (`Date.now()`, timers).77- Random number generation.78- Environment variables and configuration.7980#### When NOT to Mock81- The code under test itself.82- Pure utility functions with no side effects.83- Value objects and data structures.84- Simple internal collaborators that are fast and deterministic.8586#### Mock Quality Rules87- Mocks should match the real interface — use type-safe mocks when possible.88- Verify mock interactions only when the interaction IS the behavior (e.g., "sends an email").89- Prefer stubs (return values) over mocks (verify calls) for dependencies that provide data.90- Reset mocks between tests to prevent state leakage.9192### Step 5: Generate Tests by Type9394#### Unit Tests95- Test individual functions and methods in isolation.96- Mock all external dependencies.97- Focus on logic, calculations, transformations, validations.98- Target: cover all code paths including error branches.99100```101describe('calculateDiscount', () => {102 it('should apply 10% discount for orders over $100', () => {103 const order = createOrder({ subtotal: 150 });104 const result = calculateDiscount(order);105 expect(result).toBe(15);106 });107108 it('should return 0 discount for orders under $100', () => {109 const order = createOrder({ subtotal: 50 });110 const result = calculateDiscount(order);111 expect(result).toBe(0);112 });113114 it('should throw when order subtotal is negative', () => {115 const order = createOrder({ subtotal: -10 });116 expect(() => calculateDiscount(order)).toThrow('Invalid subtotal');117 });118});119```120121#### Integration Tests122- Test interactions between modules or services.123- Use real implementations for internal dependencies, mock external boundaries.124- Verify data flows correctly through the system.125- Test database queries against a test database (not mocked).126127```128describe('UserService.createUser', () => {129 it('should create user and send welcome email', async () => {130 const emailService = createMockEmailService();131 const service = new UserService(testDatabase, emailService);132133 const user = await service.createUser({ name: 'Jane', email: 'jane@example.com' });134135 expect(user.id).toBeDefined();136 const savedUser = await testDatabase.users.findById(user.id);137 expect(savedUser.name).toBe('Jane');138 expect(emailService.sendWelcome).toHaveBeenCalledWith('jane@example.com');139 });140});141```142143#### E2E Tests144- Test complete user workflows through the full stack.145- Use real services (or dedicated test instances).146- Focus on critical business paths — registration, checkout, core CRUD operations.147- Keep the number small — these are slow and expensive.148149### Step 6: Coverage Guidance150151| Test Type | Coverage Target | Focus |152|---|---|---|153| Unit | 80%+ line coverage | Business logic, calculations, validations |154| Integration | Critical paths covered | Service interactions, data persistence |155| E2E | Core workflows covered | User-facing flows, happy paths |156157**Coverage is a guide, not a goal.** 80% meaningful coverage is better than 100% coverage with trivial assertions. Focus on:158- Code with complex logic or many branches.159- Code that handles money, permissions, or sensitive data.160- Code that has broken before (regression tests).161162Skip testing:163- Simple getters/setters with no logic.164- Framework-generated boilerplate.165- Configuration objects with no behavior.166167## Test File Organization168169```170mobile/src/171 services/172 user-service.ts173 user-service.test.ts # Unit tests colocated174mobile/tests/175 integration/176 user-service.integration.ts # Integration tests separate177 e2e/178 user-registration.e2e.ts # E2E tests separate179 fixtures/180 users.ts # Shared test data factories181 helpers/182 test-database.ts # Test infrastructure utilities183```184185## Deep guides (read on demand, do not preload)186187The body is the workflow. The idiom for each target lives in `std-testing`'s references — which188are scoped to `**/*.test.*` / `**/*.spec.*` — and they are decision-shaped, with the bad/good189pairs. Read the one matching what you are testing rather than reconstructing it:190191- **Vitest + RTL setup, which query to reach for, MSW, providers, Zustand, Framer Motion,192 ApexCharts** → `@skills/std-testing/references/react-components.md`193- **Next.js Server Components, server actions, `generateMetadata`, route handlers** →194 `@skills/std-testing/references/nextjs-server.md`195- **React Native: RNTL, navigation, Reanimated, MMKV, Centrifugo** →196 `@skills/std-testing/references/react-native.md`197- **Unit vs integration, mock boundaries, test data builders, the edge-case matrix, Sidekiq198 jobs** → `@skills/std-testing/references/test-strategy.md`199- **Naming, the AAA structure, fixtures, mock/stub/spy guidance, test data, CI integration** →200 `references/testing-standards.md`201202This body carried its own copy of the web-frontend material until it drifted from the owner. The203copy compressed RTL's query priority to one line — `getByRole > getByLabelText > getByText >204getByTestId` — which drops `getByPlaceholderText` and, more importantly, the reason: a205`getByTestId` test passes even when the "button" is a non-focusable `<div>` with no accessible206name, so it cannot detect the accessibility regression it was supposed to catch. A summary of a207decision guide is not a smaller version of it; it is the part that does not tell you why.208209## Output210211When generating tests, provide:2121. The complete test file(s) with all test cases.2132. Any required test fixtures or factories.2143. A brief summary of what is covered and any known gaps.2154. Setup instructions if new test infrastructure is needed.