# Testing Patterns

> Auto-load when writing tests. Provides TDD workflow, test structure patterns, and common testing idioms.

- Skill: `nategarelik/testing-patterns` (Agent Skill)
- Install (CLI): `npx skillmds@latest add nategarelik/testing-patterns`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nategarelik/testing-patterns/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: nategarelik (https://skillmd.com/u/nategarelik)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/nategarelik/testing-patterns

---


# Testing Patterns

## TDD Workflow (RED-GREEN-REFACTOR)

### 1. RED: Write Failing Test First
```typescript
describe('Calculator', () => {
  it('should add two numbers', () => {
    const calc = new Calculator();
    expect(calc.add(2, 3)).toBe(5);
  });
});
```
Run test - verify it FAILS for the right reason.

### 2. GREEN: Minimal Implementation
```typescript
class Calculator {
  add(a: number, b: number): number {
    return a + b;
  }
}
```
Run test - verify it PASSES.

### 3. REFACTOR: Clean Up
Improve code while keeping tests green.

## Test Structure (AAA Pattern)

```typescript
it('should transfer money between accounts', () => {
  // Arrange - Set up test data
  const source = new Account(100);
  const target = new Account(0);

  // Act - Perform the action
  source.transfer(50, target);

  // Assert - Verify results
  expect(source.balance).toBe(50);
  expect(target.balance).toBe(50);
});
```

## What to Test

### DO Test
- Business logic and calculations
- Edge cases and boundaries
- Error handling paths
- State transitions
- Integration points

### DON'T Test
- Framework code (React, Express)
- Third-party libraries
- Simple getters/setters
- Implementation details

## Mocking Guidelines

```typescript
// Mock external dependencies
jest.mock('./api', () => ({
  fetchUser: jest.fn().mockResolvedValue({ id: 1, name: 'Test' }),
}));

// Prefer dependency injection over mocking
class UserService {
  constructor(private api: ApiClient) {}

  async getUser(id: number) {
    return this.api.fetchUser(id);
  }
}

// In tests - inject mock
const mockApi = { fetchUser: jest.fn() };
const service = new UserService(mockApi);
```

## Test Naming Convention

```typescript
describe('[Unit Under Test]', () => {
  describe('[Method/Scenario]', () => {
    it('should [expected behavior] when [condition]', () => {
      // test
    });
  });
});
```

## Async Testing

```typescript
// Async/await (preferred)
it('should fetch user', async () => {
  const user = await fetchUser(1);
  expect(user.name).toBe('Test');
});

// Testing rejections
it('should throw on invalid id', async () => {
  await expect(fetchUser(-1)).rejects.toThrow('Invalid ID');
});
```

## Coverage Targets
- Aim for 80% coverage on business logic
- 100% coverage on critical paths (auth, payments)
- Don't chase 100% everywhere - diminishing returns

