Guides TDD (test-driven development) with red-green-refactor workflows, test-first feature delivery, bug reproduction through failing tests, behavior-focused assertions, and refactoring safety. Use when writing unit tests, implementing new functions, adding test coverage, fixing regressions, changing APIs, or restructuring code under test — especially when a user says "write tests first", "TDD", or "test before code".
74
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Navigation hub for applying TDD in day-to-day implementation work.
RED — write the failing test first:
// add.test.ts
import { add } from "./add";
test("add returns the sum of two numbers", () => {
expect(add(2, 3)).toBe(5);
});
// ❌ Fails: cannot find module './add'GREEN — implement the minimum code to pass:
// add.ts
export function add(a: number, b: number): number {
return a + b;
}
// ✅ Test passesREFACTOR — improve without breaking green:
// add.ts — no logic change needed here, but you might rename,
// extract constants, or improve types while the suite stays green.
export const add = (a: number, b: number): number => a + b;
// ✅ Still green# test/math_test.exs (RED)
test "add/2 returns the sum" do
assert Math.add(2, 3) == 5
end
# lib/math.ex (GREEN)
defmodule Math do
def add(a, b), do: a + b
end# Run full suite
bun test# Watch mode while iterating
bun test --watch# Run a specific file
bun test path/to/file.test.ts# Elixir variant
mix testWHY: skipping RED phase removes behavior-first design pressure.
// BAD: production code written first, test added after
export function greet(name: string) { return `Hello, ${name}!`; }
// ... then test written to match existing impl
// GOOD: test written first, impl follows
test("greet returns a personalised greeting", () => {
expect(greet("Ada")).toBe("Hello, Ada!");
});
// ❌ red → write greet() → ✅ greenWHY: implementation-coupled tests break during valid refactors.
// BAD: asserting internal call sequence
expect(mockFormatter.format).toHaveBeenCalledBefore(mockLogger.log);
// GOOD: assert observable output
expect(result).toBe("Hello, Ada!");WHY: failures become ambiguous and debugging slows down.
// BAD: one test covers create/login/update/delete flow
test("user lifecycle", () => { /* 40 lines */ });
// GOOD: one behavior per test
test("createUser returns a user with the given name", () => { ... });
test("login returns a session token for valid credentials", () => { ... });WHY: fixed waits create flaky and slow suites.
// BAD
await sleep(1000);
expect(result).toBeDefined();
// GOOD: synchronize with deterministic signals
await expect(promise).resolves.toBeDefined();# Evaluate skill quality
sh skills/agentic-harness/skill-quality-auditor/scripts/evaluate.sh test-driven-development --json# Lint this skill docs
bunx markdownlint-cli2 "skills/test-driven-development/**/*.md"| Topic | Reference |
|---|---|
| Red-Green-Refactor cycle | references/cycle-write-test-first.md |
| Verify failing tests first | references/cycle-verify-test-fails-first.md |
| AAA and behavior-first design | references/design-aaa-pattern.md |
| Avoid implementation-detail tests | references/design-test-behavior-not-implementation.md |
| Isolation and dependency injection | references/isolate-use-dependency-injection.md |
| Flakiness and speed | references/perf-fix-flaky-tests.md |
a1083f4
Also appears in
since Jun 29, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.