Skip to content
Development
Skill

/writing-tests

Writes behavior-focused tests using Testing Trophy model with real dependencies. Use when writing tests, choosing test types, or avoiding anti-patterns like testing mocks.

BOOST
From plugin
claude-essentials
13017 skills4 agents3 commands
Install
$ npx -y skills add rileyhilliard/claude-essentials --skill writing-tests --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/writing-tests

Context preview

The summary Claude sees to decide when to auto-load this skill.

Writes behavior-focused tests using Testing Trophy model with real dependencies. Use when writing tests, choosing test types, or avoiding anti-patterns like testing mocks.

SKILL.md

writing-tests.SKILL.md
name: writing-tests
description: Writes behavior-focused tests using Testing Trophy model with real dependencies. Use when writing tests, choosing test types, or avoiding anti-patterns like testing mocks.

If the current repo has its own rules/skills covering this topic (check .claude/rules/ and repo CLAUDE.md), those take precedence — apply this skill only where they're silent.

Writing Tests

**Core principle:** Test user-observable behavior with real dependencies. Tests should survive refactoring.

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

**Why this matters:** Tests exist to give you confidence. The Testing Trophy prioritizes integration tests because they test real behavior across real modules — giving maximum confidence per test written. Unit tests in isolation often just test mocks, not your actual system.

Testing Trophy Model

| Priority | Type | When | | -------- | ----------- | ----------------------------------------------- | | 1st | Integration | Default - multiple units with real dependencies | | 2nd | E2E | Complete user workflows | | 3rd | Unit | Pure functions only (no dependencies) |

Mocking Guidelines

**Default: Don't mock. Use real dependencies.**

**Only mock:**

  • External HTTP/API calls
  • Time/randomness
  • Third-party services (payments, email)

**Never mock:**

  • Internal modules
  • Database queries (use test DB)
  • Business logic
  • Your own code calling your own code

**Before mocking, ask:** "What side effects does this have? Does my test need those?" If unsure, run with real implementation first, then add minimal mocking only where needed.

Test Type Decision

Complete user workflow? → E2E test
Pure function (no side effects)? → Unit test
Everything else → Integration test

Assertion Strategy

| Context | Assert On | Avoid | | ------- | --------------------- | --------------------------- | | UI | Visible text, roles | CSS classes, internal state | | API | Response body, status | Internal DB state | | Library | Return values | Private methods |

Anti-Patterns

| Pattern | Fix | | ------------------------------- | --------------------------- | | Testing mock calls | Test actual outcome | | Test-only methods in production | Move to test utilities | | `sleep(500)` | Poll for actual condition | | Asserting on internal state | Assert on observable output | | Incomplete mocks | Mirror real API completely |

Quality Checklist

  • [ ] Happy path covered
  • [ ] Error conditions handled
  • [ ] Real dependencies used (minimal mocking)
  • [ ] Tests survive refactoring
  • [ ] Test names describe behavior

Language-Specific Patterns

  • **JavaScript/Typescript/React**: See [references/typescript-react.md](references/typescript-react.md)
  • **Python**: See [references/python.md](references/python.md)
  • **Go**: See [references/go.md](references/go.md)

Async Waiting

Wait for the actual condition, not a guess about how long it takes.

// Bad: arbitrary delay
await new Promise(r => setTimeout(r, 2000));
expect(element).toBeVisible();

// Good: poll for condition
await waitFor(() => expect(element).toBeVisible());

**Prefer framework built-ins:**

  • Testing Library: `findBy` queries, `waitFor`
  • Playwright: auto-waiting, `expect(locator).toBeVisible()`
  • pytest: `asyncio.wait_for`, tenacity

**Language-specific waiting patterns:**

  • **TypeScript**: See [references/waiting-typescript.md](references/waiting-typescript.md)
  • **Python**: See [references/waiting-python.md](references/waiting-python.md)

---

**Remember:** Behavior over implementation. Real over mocked. Outputs over internals.

Read more
Ships withclaude-essentials

A unified development plugin for Claude Code with essential skills and specialized agents, all accessible under the ce namespace.

Get the whole plugin

Other skills on claude-essentials.