# Test Generator

> 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.

- Skill: `kaakati/test-generator` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add kaakati/test-generator`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kaakati/test-generator/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: Kaakati (https://skillmd.com/u/kaakati)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/kaakati/test-generator

---


# 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

1. Read the source file(s) to understand functionality.
2. Identify all public functions, methods, and exported interfaces.
3. Map code paths — branches, loops, error handlers, early returns.
4. Identify external dependencies — APIs, databases, file system, third-party services.
5. 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

1. **One assertion concept per test** — a test should verify one behavior. Multiple `expect` calls are fine if they verify the same logical assertion.
2. **Descriptive test names**: `should [expected behavior] when [condition/context]`
3. **No test logic** — no conditionals, loops, or try/catch in tests. If you need them, the test is too complex.
4. **Independent tests** — no shared mutable state, no execution order dependencies.
5. **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:
1. The complete test file(s) with all test cases.
2. Any required test fixtures or factories.
3. A brief summary of what is covered and any known gaps.
4. Setup instructions if new test infrastructure is needed.

