Skip to content
Back to skills

Tdd

ASecurity

Test-driven development, from unit to end-to-end tests. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration or end-to-end tests (Playwright, Cypress). Don't use to backfill tests on existing code (/refactor) or diagnose an unknown bug (/debug).

  • 16 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
ai-agentsgotestingapidatabase

Works with

  • api

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned October 11, 2026

npx -y skills add helderberto/agent-skills --skill tdd --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Tdd?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Tdd
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/helderberto-tdd/badge)](https://www.skillsdirectory.com/skills/helderberto-tdd)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: tdd
effort: high
description: Test-driven development, from unit to end-to-end tests. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration or end-to-end tests (Playwright, Cypress). Don't use to backfill tests on existing code (/refactor) or diagnose an unknown bug (/debug).
user-invocable: false
---

# Test-Driven Development

## Philosophy

**Core principle**: Tests should verify behavior through public interfaces, not implementation details. Code can change entirely; tests shouldn't.

**Good tests** are integration-style: they exercise real code paths through public APIs. They describe _what_ the system does, not _how_ it does it. A good test reads like a specification - "user can checkout with valid cart" tells you exactly what capability exists. These tests survive refactors because they don't care about internal structure.

**Bad tests** are coupled to implementation. They mock internal collaborators, test private methods, or verify through external means (like querying a database directly instead of using the interface). The warning sign: your test breaks when you refactor, but behavior hasn't changed. If you rename an internal function and tests fail, those tests were testing implementation, not behavior.

See [tests.md](references/tests.md) for examples, [mocking.md](references/mocking.md) for mocking guidelines, and [ui-tests.md](references/ui-tests.md) for end-to-end tests of user flows.

## Anti-Pattern: Horizontal Slices

**DO NOT write all tests first, then all implementation.** This is "horizontal slicing" - treating RED as "write all tests" and GREEN as "write all code."

This produces **crap tests**:

- Tests written in bulk test _imagined_ behavior, not _actual_ behavior
- You end up testing the _shape_ of things (data structures, function signatures) rather than user-facing behavior
- Tests become insensitive to real changes - they pass when behavior breaks, fail when behavior is fine
- You outrun your headlights, committing to test structure before understanding the implementation

**Correct approach**: Vertical slices via tracer bullets. One test → one implementation → repeat. Each test responds to what you learned from the previous cycle. Because you just wrote the code, you know exactly what behavior matters and how to verify it.

```
WRONG (horizontal):
  RED:   test1, test2, test3, test4, test5
  GREEN: impl1, impl2, impl3, impl4, impl5

RIGHT (vertical):
  RED→GREEN: test1→impl1
  RED→GREEN: test2→impl2
  RED→GREEN: test3→impl3
  ...
```

## Anti-Pattern: Tautological Tests

The assertion recomputes the expected value the same way the code does — `expect(add(a, b)).toBe(a + b)`, a snapshot derived by hand via the same logic, a constant asserted equal to itself. The test passes by construction and can never disagree with the code.

**Expected values must come from an independent source of truth**: a known-good literal, a worked example, the spec. See [tests.md](references/tests.md) for an example.

## Workflow

### 0. Discover the stack

The TDD cycle is universal; the commands are not. Before the first test, discover how _this_ repository tests and use its commands for every RED and GREEN:

- Build system: `package.json`, `pyproject.toml`, `go.mod`, `Cargo.toml`, `Makefile`
- Checked-in wrappers first: `./gradlew`, `./mvnw`, `make test`, repo scripts — never a globally installed tool the repo doesn't use
- The focused-single-test command vs the full-suite command — run focused during the loop, full suite once before completion
- Where tests live, how they're named, what patterns neighboring tests follow
- CI workflows show the commands that actually gate merges

Never assume `npm test`.

### 1. Planning

When exploring the codebase, read `GLOSSARY.md` if it exists (else a legacy `CONTEXT.md`; `GLOSSARY-MAP.md` points to the right one in a multi-context repo) so that test names and interface vocabulary match the project's domain language, and respect ADRs in the area you're touching.

A **seam** is the public boundary you test at: the interface where you observe behavior without reaching inside. Before writing any test, write down the seams under test, one line each on what a test there catches and what it misses, and confirm them with the user:

Ask: "What's the public interface, and which seams should we test?"

**No test is written at an unconfirmed seam.**

Before writing any code:

- [ ] Confirm the seams under test with the user
- [ ] Confirm with user which behaviors to test (prioritize)
- [ ] Identify opportunities for deep modules (small interface, deep implementation) — call the Skill tool with `codebase-design` for the vocabulary and the testability checks
- [ ] List the behaviors to test (not implementation steps)
- [ ] Get user approval on the plan

**You can't test everything.** Agreeing the seams up front is how testing effort lands on critical paths and complex logic, not every possible edge case.

### 2. Tracer Bullet

Write ONE test that confirms ONE thing about the system:

```
RED:   Write test for first behavior → test fails
GREEN: Write minimal code to pass → test passes
```

This is your tracer bullet - proves the path works end-to-end.

### 3. Incremental Loop

For each remaining behavior:

```
RED:   Write next test → fails
GREEN: Minimal code to pass → passes
```

Rules:

- One test at a time
- Only enough code to pass current test
- Don't anticipate future tests
- Keep tests focused on observable behavior

### 4. Refactor

Only once GREEN — never while RED. Extract duplication, deepen modules (call the Skill tool with `codebase-design` for the vocabulary), and ask what the new code reveals about existing code. Run tests after each step.

Files in this skill

  • SKILL.md5.7 KB
  • references/mocking.md1.8 KB
  • references/tests.md2.2 KB
  • references/ui-tests.md977 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…