testing-patterns

Write effective tests across the stack—unit, integration, E2E, and visual regression. Covers testing philosophy, framework selection, mocking strategies, and CI integration. Triggers on testing, test coverage, TDD, or quality assurance requests.

Best use case

testing-patterns is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Write effective tests across the stack—unit, integration, E2E, and visual regression. Covers testing philosophy, framework selection, mocking strategies, and CI integration. Triggers on testing, test coverage, TDD, or quality assurance requests.

Teams using testing-patterns should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/testing-patterns/SKILL.md --create-dirs "https://raw.githubusercontent.com/organvm-iv-taxis/a-i--skills/main/distributions/claude/skills/testing-patterns/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/testing-patterns/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How testing-patterns Compares

Feature / Agenttesting-patternsStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Write effective tests across the stack—unit, integration, E2E, and visual regression. Covers testing philosophy, framework selection, mocking strategies, and CI integration. Triggers on testing, test coverage, TDD, or quality assurance requests.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Testing Patterns

Build confidence through strategic testing.

## Testing Philosophy

### The Testing Trophy

```
        ╱╲
       ╱  ╲        E2E (few)
      ╱────╲       
     ╱      ╲      Integration (more)
    ╱────────╲     
   ╱          ╲    Unit (many, fast)
  ╱────────────╲   
 ╱   Static     ╲  TypeScript, ESLint
╱────────────────╲
```

### What to Test

| Test Type | What | Why |
|-----------|------|-----|
| Static | Types, lint rules | Catch errors at write-time |
| Unit | Pure functions, utils | Fast, precise feedback |
| Integration | Component + dependencies | Test contracts |
| E2E | User flows | Confidence in real usage |

### What NOT to Test

- Implementation details (internal state, private methods)
- Third-party library internals
- Constants and configuration
- Framework code

---

## Unit Testing

### Structure: AAA Pattern

```typescript
describe('calculateTotal', () => {
  it('should apply discount to subtotal', () => {
    // Arrange
    const items = [{ price: 100 }, { price: 50 }];
    const discount = 0.1;
    
    // Act
    const result = calculateTotal(items, discount);
    
    // Assert
    expect(result).toBe(135);
  });
});
```

### Test Naming

```typescript
// Pattern: should [expected behavior] when [condition]

it('should return empty array when input is null')
it('should throw error when user is not authenticated')
it('should apply discount when coupon is valid')
```

### Testing Pure Functions

```typescript
// utils/format.ts
export function formatCurrency(cents: number): string {
  return `$${(cents / 100).toFixed(2)}`;
}

// utils/format.test.ts
describe('formatCurrency', () => {
  it('should format cents to dollar string', () => {
    expect(formatCurrency(1000)).toBe('$10.00');
    expect(formatCurrency(1)).toBe('$0.01');
    expect(formatCurrency(0)).toBe('$0.00');
  });

  it('should handle negative values', () => {
    expect(formatCurrency(-500)).toBe('$-5.00');
  });
});
```

### Edge Cases to Consider

- Empty/null/undefined inputs
- Boundary values (0, -1, MAX_INT)
- Empty arrays/objects
- Invalid types (if not using TypeScript)
- Async edge cases (race conditions, timeouts)

---

## React Component Testing

### Testing Library Philosophy

> "The more your tests resemble the way your software is used, the more confidence they can give you."

### Component Test Structure

```tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { Counter } from './Counter';

describe('Counter', () => {
  it('should increment count when button clicked', async () => {
    render(<Counter initialCount={0} />);
    
    const button = screen.getByRole('button', { name: /increment/i });
    await fireEvent.click(button);
    
    expect(screen.getByText('Count: 1')).toBeInTheDocument();
  });
});
```

### Query Priority

Use queries in this order (most to least preferred):

1. `getByRole` - Accessible to everyone
2. `getByLabelText` - Form fields
3. `getByPlaceholderText` - If no label
4. `getByText` - Non-interactive content
5. `getByTestId` - Last resort

### Async Testing

```tsx
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

it('should load data after button click', async () => {
  const user = userEvent.setup();
  render(<DataLoader />);
  
  await user.click(screen.getByRole('button', { name: /load/i }));
  
  // Wait for async content
  await waitFor(() => {
    expect(screen.getByText('Data loaded')).toBeInTheDocument();
  });
});
```

### Mocking

```tsx
// Mock a module
vi.mock('./api', () => ({
  fetchUser: vi.fn(() => Promise.resolve({ name: 'Test User' })),
}));

// Mock a hook
vi.mock('./useAuth', () => ({
  useAuth: () => ({ user: { id: '1' }, isLoading: false }),
}));

// Mock fetch
global.fetch = vi.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({ data: 'test' }),
  })
);
```

---

## Integration Testing

### API Route Testing

```typescript
import { createMocks } from 'node-mocks-http';
import handler from './api/posts';

describe('/api/posts', () => {
  it('should return posts list', async () => {
    const { req, res } = createMocks({
      method: 'GET',
    });

    await handler(req, res);

    expect(res._getStatusCode()).toBe(200);
    expect(JSON.parse(res._getData())).toHaveLength(3);
  });
});
```

### Database Integration

```typescript
import { db } from '@/lib/db';

describe('User service', () => {
  beforeEach(async () => {
    await db.user.deleteMany(); // Clean state
  });

  afterAll(async () => {
    await db.$disconnect();
  });

  it('should create user with valid data', async () => {
    const user = await createUser({ 
      email: 'test@example.com',
      name: 'Test User' 
    });

    expect(user.id).toBeDefined();
    expect(user.email).toBe('test@example.com');
  });
});
```

---

## E2E Testing

### Playwright Setup

```typescript
// e2e/auth.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Authentication', () => {
  test('should allow user to sign in', async ({ page }) => {
    await page.goto('/login');
    
    await page.fill('[name="email"]', 'user@example.com');
    await page.fill('[name="password"]', 'password123');
    await page.click('button[type="submit"]');
    
    await expect(page).toHaveURL('/dashboard');
    await expect(page.locator('h1')).toContainText('Welcome');
  });
});
```

### Page Object Pattern

```typescript
// e2e/pages/login.page.ts
export class LoginPage {
  constructor(private page: Page) {}

  async goto() {
    await this.page.goto('/login');
  }

  async login(email: string, password: string) { <!-- allow-secret -->
    await this.page.fill('[name="email"]', email);
    await this.page.fill('[name="password"]', password);
    await this.page.click('button[type="submit"]');
  }
}

// e2e/auth.spec.ts
test('should login successfully', async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.goto();
  await loginPage.login('user@example.com', 'password');
  
  await expect(page).toHaveURL('/dashboard');
});
```

### Visual Regression

```typescript
test('homepage should match snapshot', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveScreenshot('homepage.png');
});
```

---

## Mocking Strategies

### When to Mock

| Mock | When |
|------|------|
| External APIs | Always in unit/integration |
| Database | Sometimes (test containers vs mocks) |
| Time/Date | When testing time-dependent logic |
| Randomness | When testing deterministic output |
| Network | Always in unit tests |

### MSW (Mock Service Worker)

```typescript
// mocks/handlers.ts
import { rest } from 'msw';

export const handlers = [
  rest.get('/api/users', (req, res, ctx) => {
    return res(
      ctx.json([
        { id: 1, name: 'John' },
        { id: 2, name: 'Jane' },
      ])
    );
  }),
  
  rest.post('/api/users', async (req, res, ctx) => {
    const body = await req.json();
    return res(ctx.status(201), ctx.json({ id: 3, ...body }));
  }),
];
```

---

## Test Configuration

### Vitest Config

```typescript
// vitest.config.ts
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  test: {
    environment: 'jsdom',
    globals: true,
    setupFiles: ['./test/setup.ts'],
    coverage: {
      reporter: ['text', 'html'],
      exclude: ['node_modules/', 'test/'],
    },
  },
});
```

### Test Setup

```typescript
// test/setup.ts
import '@testing-library/jest-dom';
import { server } from './mocks/server';

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
```

---

## Coverage Strategy

### Meaningful Coverage

| Type | Target | Notes |
|------|--------|-------|
| Statements | 70-80% | Don't chase 100% |
| Branches | 70-80% | Test important paths |
| Functions | 80%+ | All public APIs |
| Lines | 70-80% | Balance with velocity |

### What High Coverage Doesn't Mean

- Tests are good
- No bugs
- Code is maintainable
- Edge cases are covered

---

## CI Integration

```yaml
# .github/workflows/test.yml
name: Test
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      
      - run: npm ci
      - run: npm run test:coverage
      
      - uses: codecov/codecov-action@v3
        with:
          files: ./coverage/lcov.info
```

---

---

## Related Skills

### Complementary Skills (Use Together)
- **[tdd-workflow](../tdd-workflow/)** - Test-driven development workflow; combine with testing-patterns for complete TDD practice
- **[verification-loop](../verification-loop/)** - Iterative verification process that uses tests as quality gates
- **[deployment-cicd](../deployment-cicd/)** - CI/CD integration for running tests in pipelines

### Alternative Skills (Similar Purpose)
- **[webapp-testing](../webapp-testing/)** - Specialized web application testing with browser automation focus

### Prerequisite Skills (Learn First)
- None required - this is a foundational skill

---

## References

- `references/vitest-patterns.md` - Vitest specific patterns
- `references/playwright-patterns.md` - E2E testing patterns
- `references/mock-examples.md` - Mocking recipes

Related Skills

webhook-integration-patterns

5
from organvm-iv-taxis/a-i--skills

Designs reliable webhook systems with proper delivery guarantees, retry logic, signature verification, and idempotent processing for event-driven integrations.

webapp-testing

5
from organvm-iv-taxis/a-i--skills

Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.

vector-search-patterns

5
from organvm-iv-taxis/a-i--skills

Implement vector similarity search with embedding generation, index selection, and hybrid retrieval strategies. Covers ChromaDB, pgvector, FAISS, and RAG pipeline design. Triggers on vector search, embeddings, semantic search, or RAG architecture requests.

session-lifecycle-patterns

5
from organvm-iv-taxis/a-i--skills

Manage AI agent session lifecycles with structured phases (FRAME, SHAPE, BUILD, PROVE), context preservation across sessions, handoff protocols, and session metadata tracking. Triggers on session management, agent lifecycle, or multi-session workflow requests.

responsive-design-patterns

5
from organvm-iv-taxis/a-i--skills

Mobile-first responsive design patterns with breakpoints, fluid layouts, and adaptive components

resilience-patterns

5
from organvm-iv-taxis/a-i--skills

Build fault-tolerant systems with circuit breakers, retries with backoff, bulkheads, timeouts, and graceful degradation. Covers distributed system failure modes and recovery strategies. Triggers on reliability engineering, fault tolerance, or distributed system resilience requests.

redis-patterns

5
from organvm-iv-taxis/a-i--skills

Use Redis effectively for caching, pub/sub messaging, rate limiting, distributed locks, and session storage. Covers data structure selection, expiration strategies, and cluster patterns. Triggers on Redis usage, caching architecture, or pub/sub messaging requests.

realtime-websocket-patterns

5
from organvm-iv-taxis/a-i--skills

Implement real-time features with WebSockets, Server-Sent Events, and long polling. Covers connection management, room-based messaging, presence tracking, and scaling strategies. Triggers on WebSocket implementation, real-time communication, or live update feature requests.

react-three-fiber-patterns

5
from organvm-iv-taxis/a-i--skills

Build interactive 3D experiences in React using react-three-fiber (R3F), drei helpers, and shader integration. Covers scene composition, performance optimization, and animation patterns. Triggers on R3F development, React + Three.js, or declarative 3D scene requests.

python-packaging-patterns

5
from organvm-iv-taxis/a-i--skills

Structure Python projects for distribution with pyproject.toml, src layouts, dependency management, and publishing workflows. Covers packaging tools (hatch, setuptools, flit, poetry), versioning strategies, and editable installs. Triggers on Python project setup, packaging configuration, or dependency management requests.

prompt-engineering-patterns

5
from organvm-iv-taxis/a-i--skills

Design effective prompts for LLM agents with structured input/output formats, chain-of-thought reasoning, few-shot examples, and system prompt architecture. Covers Claude-specific patterns and multi-turn conversation design. Triggers on prompt design, LLM interaction patterns, or system prompt architecture requests.

postgres-advanced-patterns

5
from organvm-iv-taxis/a-i--skills

Advanced PostgreSQL patterns for performance optimization, complex queries, indexing strategies, and database design