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.4---56# Test Generator78Generate 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.910## Test Generation Workflow1112### Step 1: Analyze the Code Under Test13141. Read the source file(s) to understand functionality.152. Identify all public functions, methods, and exported interfaces.163. Map code paths — branches, loops, error handlers, early returns.174. Identify external dependencies — APIs, databases, file system, third-party services.185. Note any existing tests to avoid duplication and maintain consistency.1920### Step 2: Identify Test Cases2122For each function or method, identify:2324#### Happy Path Cases25- Standard inputs producing expected outputs.26- Common use cases as described in requirements or documentation.2728#### Edge Cases29- **Null/undefined/empty inputs**: What happens with no data?30- **Boundary values**: Minimum, maximum, zero, negative numbers, empty strings, single-character strings.31- **Type boundaries**: Integer overflow, floating point precision, very long strings.32- **Collection edges**: Empty array, single element, very large collections.33- **Concurrent access**: Race conditions, simultaneous modifications.3435#### Error Cases36- Invalid input types or formats.37- Missing required fields.38- External service failures (network errors, timeouts, 5xx responses).39- Permission/authorization failures.40- Resource not found scenarios.41- Data constraint violations (unique, foreign key, validation).4243#### State Transitions44- Before/after states for mutations.45- Idempotency verification — calling twice produces the same result.46- Order-dependent behavior.4748### Step 3: Write Tests Using AAA Pattern4950Every test follows **Arrange, Act, Assert**:5152```53// Arrange — set up test data, mocks, and preconditions54// Act — execute the function or operation under test55// Assert — verify the outcome matches expectations56```5758#### Test Structure Rules59601. **One assertion concept per test** — a test should verify one behavior. Multiple `expect` calls are fine if they verify the same logical assertion.612. **Descriptive test names**: `should [expected behavior] when [condition/context]`623. **No test logic** — no conditionals, loops, or try/catch in tests. If you need them, the test is too complex.634. **Independent tests** — no shared mutable state, no execution order dependencies.645. **Fast tests** — unit tests should run in milliseconds. Mock external dependencies.6566### Step 4: Apply Mocking Strategy6768#### When to Mock69- External HTTP APIs and services.70- Database connections and queries.71- File system operations.72- Time-dependent operations (`Date.now()`, timers).73- Random number generation.74- Environment variables and configuration.7576#### When NOT to Mock77- The code under test itself.78- Pure utility functions with no side effects.79- Value objects and data structures.80- Simple internal collaborators that are fast and deterministic.8182#### Mock Quality Rules83- Mocks should match the real interface — use type-safe mocks when possible.84- Verify mock interactions only when the interaction IS the behavior (e.g., "sends an email").85- Prefer stubs (return values) over mocks (verify calls) for dependencies that provide data.86- Reset mocks between tests to prevent state leakage.8788### Step 5: Generate Tests by Type8990#### Unit Tests91- Test individual functions and methods in isolation.92- Mock all external dependencies.93- Focus on logic, calculations, transformations, validations.94- Target: cover all code paths including error branches.9596```97describe('calculateDiscount', () => {98 it('should apply 10% discount for orders over $100', () => {99 const order = createOrder({ subtotal: 150 });100 const result = calculateDiscount(order);101 expect(result).toBe(15);102 });103104 it('should return 0 discount for orders under $100', () => {105 const order = createOrder({ subtotal: 50 });106 const result = calculateDiscount(order);107 expect(result).toBe(0);108 });109110 it('should throw when order subtotal is negative', () => {111 const order = createOrder({ subtotal: -10 });112 expect(() => calculateDiscount(order)).toThrow('Invalid subtotal');113 });114});115```116117#### Integration Tests118- Test interactions between modules or services.119- Use real implementations for internal dependencies, mock external boundaries.120- Verify data flows correctly through the system.121- Test database queries against a test database (not mocked).122123```124describe('UserService.createUser', () => {125 it('should create user and send welcome email', async () => {126 const emailService = createMockEmailService();127 const service = new UserService(testDatabase, emailService);128129 const user = await service.createUser({ name: 'Jane', email: 'jane@example.com' });130131 expect(user.id).toBeDefined();132 const savedUser = await testDatabase.users.findById(user.id);133 expect(savedUser.name).toBe('Jane');134 expect(emailService.sendWelcome).toHaveBeenCalledWith('jane@example.com');135 });136});137```138139#### E2E Tests140- Test complete user workflows through the full stack.141- Use real services (or dedicated test instances).142- Focus on critical business paths — registration, checkout, core CRUD operations.143- Keep the number small — these are slow and expensive.144145### Step 6: Coverage Guidance146147| Test Type | Coverage Target | Focus |148|---|---|---|149| Unit | 80%+ line coverage | Business logic, calculations, validations |150| Integration | Critical paths covered | Service interactions, data persistence |151| E2E | Core workflows covered | User-facing flows, happy paths |152153**Coverage is a guide, not a goal.** 80% meaningful coverage is better than 100% coverage with trivial assertions. Focus on:154- Code with complex logic or many branches.155- Code that handles money, permissions, or sensitive data.156- Code that has broken before (regression tests).157158Skip testing:159- Simple getters/setters with no logic.160- Framework-generated boilerplate.161- Configuration objects with no behavior.162163## Test File Organization164165```166mobile/src/167 services/168 user-service.ts169 user-service.test.ts # Unit tests colocated170mobile/tests/171 integration/172 user-service.integration.ts # Integration tests separate173 e2e/174 user-registration.e2e.ts # E2E tests separate175 fixtures/176 users.ts # Shared test data factories177 helpers/178 test-database.ts # Test infrastructure utilities179```180181## Deep guides (read on demand, do not preload)182183The body is the workflow. The idiom for each target lives in `std-testing`'s references — which184are scoped to `**/*.test.*` / `**/*.spec.*` — and they are decision-shaped, with the bad/good185pairs. Read the one matching what you are testing rather than reconstructing it:186187- **Vitest + RTL setup, which query to reach for, MSW, providers, Zustand, Framer Motion,188 ApexCharts** → `@skills/std-testing/references/react-components.md`189- **Next.js Server Components, server actions, `generateMetadata`, route handlers** →190 `@skills/std-testing/references/nextjs-server.md`191- **React Native: RNTL, navigation, Reanimated, MMKV, Centrifugo** →192 `@skills/std-testing/references/react-native.md`193- **Unit vs integration, mock boundaries, test data builders, the edge-case matrix, Sidekiq194 jobs** → `@skills/std-testing/references/test-strategy.md`195- **Naming, the AAA structure, fixtures, mock/stub/spy guidance, test data, CI integration** →196 `references/testing-standards.md`197198This body carried its own copy of the web-frontend material until it drifted from the owner. The199copy compressed RTL's query priority to one line — `getByRole > getByLabelText > getByText >200getByTestId` — which drops `getByPlaceholderText` and, more importantly, the reason: a201`getByTestId` test passes even when the "button" is a non-focusable `<div>` with no accessible202name, so it cannot detect the accessibility regression it was supposed to catch. A summary of a203decision guide is not a smaller version of it; it is the part that does not tell you why.204205## Output206207When generating tests, provide:2081. The complete test file(s) with all test cases.2092. Any required test fixtures or factories.2103. A brief summary of what is covered and any known gaps.2114. Setup instructions if new test infrastructure is needed.