home / skills / 0xdarkmatter / claude-mods / testing-patterns

testing-patterns skill

/skills/testing-patterns

This skill helps you implement robust testing strategies across languages by applying the test pyramid, AAA, and test doubles to improve quality.

npx playbooks add skill 0xdarkmatter/claude-mods --skill testing-patterns

Review the files below or copy the command above to add this skill to your agents.

Files (7)
SKILL.md
4.1 KB
---
name: testing-patterns
description: "Cross-language testing strategies and patterns. Triggers on: test pyramid, unit test, integration test, e2e test, TDD, BDD, test coverage, mocking strategy, test doubles, test isolation."
compatibility: "Language-agnostic patterns. Framework-specific details in references."
allowed-tools: "Read Write Bash"
---

# Testing Patterns

Universal testing strategies and patterns applicable across languages.

## The Test Pyramid

```
        /\
       /  \     E2E Tests (few, slow, expensive)
      /    \    - Full system tests
     /------\   - Real browser/API calls
    /        \
   /  Integ   \ Integration Tests (some)
  /   Tests    \ - Service boundaries
 /--------------\ - Database, APIs
/                \
/   Unit Tests    \ Unit Tests (many, fast, cheap)
------------------  - Single function/class
                    - Mocked dependencies
```

## Test Types

### Unit Tests
```
Scope:      Single function/method/class
Speed:      Milliseconds
Dependencies: All mocked
When:       Every code change
Coverage:   80%+ of codebase
```

### Integration Tests
```
Scope:      Multiple components together
Speed:      Seconds
Dependencies: Real databases, mocked external APIs
When:       PR/merge, critical paths
Coverage:   Key integration points
```

### End-to-End Tests
```
Scope:      Full user journey
Speed:      Minutes
Dependencies: Real system (or staging)
When:       Pre-deploy, nightly
Coverage:   Critical user flows only
```

## Test Naming Convention

```
test_<unit>_<scenario>_<expected>

Examples:
- test_calculate_total_with_discount_returns_reduced_price
- test_user_login_with_invalid_password_returns_401
- test_order_submit_when_out_of_stock_raises_error
```

## Arrange-Act-Assert (AAA)

```python
def test_calculate_discount():
    # Arrange - Set up test data and dependencies
    cart = Cart()
    cart.add_item(Item(price=100))
    discount = Discount(percent=10)

    # Act - Execute the code under test
    total = cart.calculate_total(discount)

    # Assert - Verify the results
    assert total == 90
```

## Test Doubles

| Type | Purpose | Example |
|------|---------|---------|
| **Stub** | Returns canned data | `stub.get_user.returns(fake_user)` |
| **Mock** | Verifies interactions | `mock.send_email.assert_called_once()` |
| **Spy** | Records calls, uses real impl | `spy.on(service, 'save')` |
| **Fake** | Working simplified impl | `FakeDatabase()` instead of real DB |
| **Dummy** | Placeholder, never used | `null` object for required param |

## Test Isolation Strategies

### Database Isolation
```
Option 1: Transaction rollback (fast)
- Start transaction before test
- Rollback after test

Option 2: Truncate tables (medium)
- Clear all data between tests

Option 3: Separate database (slow)
- Each test gets fresh database
```

### External Service Isolation
```
Option 1: Mock at boundary
- Replace HTTP client with mock

Option 2: Fake server
- WireMock, MSW, VCR cassettes

Option 3: Contract testing
- Pact, consumer-driven contracts
```

## What to Test

### MUST Test
- Business logic and calculations
- Input validation and error handling
- Security-sensitive code (auth, permissions)
- Edge cases and boundary conditions

### SHOULD Test
- Integration points (DB, APIs)
- State transitions
- Configuration handling

### AVOID Testing
- Framework internals
- Third-party library behavior
- Simple getters/setters
- Private implementation details

## Test Quality Checklist

- [ ] Tests are independent (no order dependency)
- [ ] Tests are deterministic (no flaky tests)
- [ ] Tests are fast (unit < 100ms, integration < 5s)
- [ ] Tests have clear names describing behavior
- [ ] Tests cover happy path AND error cases
- [ ] Tests don't repeat production logic
- [ ] Mocks are minimal (only external boundaries)

## Additional Resources

- `./references/tdd-workflow.md` - Test-Driven Development cycle
- `./references/mocking-strategies.md` - When and how to mock
- `./references/test-data-patterns.md` - Fixtures, factories, builders
- `./references/ci-testing.md` - Testing in CI/CD pipelines

## Scripts

- `./scripts/coverage-check.sh` - Run coverage and fail if below threshold

Overview

This skill provides cross-language testing strategies and concrete patterns to build reliable, fast, and maintainable test suites. It codifies the test pyramid, test types, naming conventions, arrange-act-assert structure, test doubles, and isolation options. Use it to standardize how teams write and run unit, integration, and end-to-end tests.

How this skill works

The skill inspects common testing concerns and recommends patterns for scope, speed, and dependencies across test types. It describes naming conventions, Arrange-Act-Assert flow, and when to use each test double (stub, mock, spy, fake, dummy). It also catalogs database and external service isolation techniques and a practical test quality checklist you can apply in CI pipelines.

When to use it

  • Establishing a team-wide testing strategy or onboarding new engineers
  • Designing CI jobs and deciding which tests to run at each stage
  • Choosing isolation approaches for databases and external services
  • Defining test naming and AAA structure for clearer, maintainable tests
  • Evaluating test coverage and trimming flaky or slow tests

Best practices

  • Favor a test pyramid: many fast unit tests, fewer integration tests, and minimal E2E tests
  • Name tests with intent: test_<unit>_<scenario>_<expected> for readable failure signals
  • Apply Arrange-Act-Assert to keep tests clear and focused
  • Prefer transaction rollback or in-memory fakes for fast DB isolation; use separate databases only when necessary
  • Mock only external boundaries; prefer fakes or contract tests for third-party services

Example use cases

  • Create a new microservice test suite: start with 80%+ unit tests, add integration tests for DB interactions, reserve E2E for user flows
  • Refactor test suite to remove flakiness: add deterministic data setup and transactional rollbacks
  • Design CI pipeline: run unit tests on every PR, integration tests on merge, nightly E2E for full-user journeys
  • Implement mocking strategy: use stubs for canned responses, spies to verify save calls, and fakes for local development

FAQ

What coverage target should I aim for?

Aim for 80%+ overall while prioritizing meaningful tests for business logic and critical paths rather than aiming for 100% indiscriminately.

When should I choose a fake versus a mock?

Use fakes when a simplified working implementation is helpful for local tests; use mocks when you need to verify interactions or enforce that specific calls occur.