Tdd patterns
Skill synaptiai/synapti-marketplace/plugins/flow/skills/tdd-patterns
The Synapti Marketplace is a curated collection of Claude Code plugins designed for AI-augmented development + advanced analytical and research tasks. Each plugin provides specialized agents, skills, and commands that extend Claude Code's capabilities in specific domains.
npx -y skills add synaptiai/synapti-marketplace --skill tdd-patternsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Guide test-driven development through the mandatory Red-Green-Refactor cycle (failing test before code), enforce test quality (one behavior per test, real code over mocks, no implementation-detail testing), and enforce test runner discipline (run mode, no watch mode). Use when implementing features or fixing bugs (with `testing.tddMode='enforce'` blocking implementation without a failing test). This skill MUST be consulted because test-first is the primary quality enforcement point; tests that pass on first write are suspect (likely testing the wrong thing).
SKILL.md
6.7 KB, as published. Nobody here has run it
TDD Patterns
Domain skill for test-driven development: Red-Green-Refactor cycle, test quality, and runner discipline.
Iron Law
IF YOU DIDN'T WATCH THE TEST FAIL, YOU DON'T KNOW IF IT TESTS THE RIGHT THING.
A test that has never failed might pass for the wrong reason. The RED phase exists to prove the test is valid.
Red-Green-Refactor Cycle
For each feature or fix, track the TDD cycle with tasks:
TaskCreate("RED: Write failing test for {behavior}", "Minimal test describing desired behavior. MUST fail on first run.")
TaskCreate("GREEN: Implement {behavior}", "Simplest code to make the test pass. No cleverness.")
TaskCreate("REFACTOR: Clean up {behavior}", "Improve quality. All tests must still pass after each step.")
RED: Write a Failing Test
TaskUpdate(RED task, status: "in_progress")
- Write the minimal test that describes the desired behavior
- Run it — it MUST fail
- Verify it fails for the right reason (not a syntax error, not wrong import)
TaskUpdate(RED task, status: "completed")
GREEN: Make It Pass
TaskUpdate(GREEN task, status: "in_progress")
- Write the simplest code that makes the test pass
- No cleverness. No optimization. No "while I'm here" improvements.
- Run the test — it MUST pass now
TaskUpdate(GREEN task, status: "completed")
REFACTOR: Clean Up
TaskUpdate(REFACTOR task, status: "in_progress")
- Improve code quality (naming, structure, duplication)
- Run ALL tests after each refactor step — they must still pass
- No new functionality during refactor — that's a new RED phase
TaskUpdate(REFACTOR task, status: "completed") Use TaskList to confirm the full cycle completed before moving to the next behavior.
The cycle is non-negotiable. RED → GREEN → REFACTOR. Always in this order.
Test Runner Discipline
Always use run mode, never watch mode:
| Framework | Correct | Wrong |
|---|---|---|
| Vitest | vitest run | vitest (watch) |
| Jest | CI=true jest or jest --watchAll=false | jest (watch) |
| Pytest | pytest | — |
| RSpec | rspec | guard (watch) |
Watch mode leaves orphan processes. Verify cleanup:
pgrep -f "vitest|jest|pytest" && echo "ORPHAN PROCESS — kill it"
Test Quality Standards
One Behavior Per Test
# GOOD: Each test verifies one thing
test "returns empty array when no items match"
test "returns matching items sorted by relevance"
# BAD: Multiple behaviors in one test
test "search works correctly" # What does "correctly" mean?
Descriptive Names
Test names should read as specifications:
- "creates user with valid email"
- "rejects duplicate usernames"
- "returns 404 when resource not found"
Real Code Over Mocks
- Mock ONLY at external boundaries (APIs, databases, file system)
- Never mock the code under test
- Never mock internal collaborators unless they have side effects
- If you need many mocks, the design needs improvement
No Testing Implementation Details
- Test behavior (what), not implementation (how)
- Don't assert on internal state, private methods, or call counts
- If refactoring breaks tests but not behavior, the tests are wrong
When TDD Applies
| Scenario | TDD? | Notes |
|---|---|---|
| New feature | Always | Define behavior before implementing |
| Bug fix | Always | Write reproducing test first |
| Refactor | Existing tests | Ensure tests pass before AND after |
| Prototype/spike | Optional | But write tests before merging |
| Config changes | No | Unless behavior changes |
Process Enforcement
Check settings.json → testing.tddMode:
| Mode | Default? | Behavior |
|---|---|---|
enforce | Yes | Block implementation without a failing test. No exceptions. The RED phase must produce a failing test before any production code is written. |
suggest | No (opt-in) | Recommend TDD. Allow override with explicit user decision. |
off | No (opt-in) | No TDD guidance. Tests still run in verification. |
Opt-out mechanism
enforce is the default because skipping the RED phase is the #1 source of tests that pass for the wrong reason. Teams that need the old suggest behavior can opt out:
{
"testing": {
"tddMode": "suggest",
"tddModeOptOut": true
}
}
Set testing.tddModeOptOut to true in settings.json to switch tddMode back to suggest. When tddModeOptOut is false (the default), tddMode must remain enforce. This two-field design ensures the opt-out is an explicit, auditable decision rather than a silent default change.
Coverage Targets
Aim for meaningful coverage, not vanity metrics:
- 80%+ for branches, functions, lines, statements
- 100% for critical paths (auth, payments, data mutations)
- 0% is acceptable for generated code, config files, type definitions
Rationalization Prevention
| Excuse | Response |
|---|---|
| "Skip TDD just this once" | Delete the code. Start over. The cycle is the discipline. |
| "This is too simple to test" | Simple code, simple test. Write it in 30 seconds. |
| "I'll write tests after" | You won't. And if you do, they'll test what you wrote, not what you should have written. |
| "Tests slow me down" | Tests slow you down NOW. Bugs slow you down FOREVER. |
| "The test passes on first try" | That's a red flag. It should have failed first. Check: is it testing the right thing? |
Stop Conditions
| Trigger | Action |
|---|---|
| Test passes immediately on first write | Test is suspect. Verify it fails when you break the code intentionally. |
| >3 tests needed for one function | Function may be doing too much. Consider splitting. |
| Mocking >2 dependencies | Design smell. Refactor to reduce coupling. |
| Test is harder to write than the code | Step back. Either the interface is wrong or the test is testing implementation. |