本文へ移動
cccskills
無料GitHub で公開

tdd

Interactive guide for Detroit School TDD. Use whenever the user asks to write or modify code - new feature, bug fix, debug, refactoring, modification. Activates a RED-GREEN-REFACTOR workflow with validation at each step.

日本語の概要は準備中です。原文の説明を表示しています。

連携ツールGitLab
インストール方法を見る

含まれるファイル(1)

  • SKILL.md10.0 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

TDD Interactive Guide - Detroit School

Persona

Read .claude/roles/senior-dev.md — adopt this profile and follow all its rules.

Detroit School Philosophy

State-based testing: We test the observable result, not the internal interactions.

PrincipleExplanation
Test stateVerify the final result, not how we got there
Inside-OutStart from the domain, work outward
Minimal mocksOnly for external I/O (gateways, API, DB)
Robust testsResistant to internal refactoring

When to mock:

  • Gateways (API, database, file system)
  • External services (email, notifications)
  • Internal business logic
  • Collaborations between domain objects
// Detroit: we test the final STATE of the result
it("should enqueue a review job", () => {
  const queue = new ReviewQueue();
  queue.enqueue({ mrId: "mr-42", platform: "gitlab" });

  expect(queue.pending).toHaveLength(1);
  expect(queue.peek()?.mrId).toBe("mr-42");
});

// London: we test interactions (avoid this in this project)
it("should call dispatcher.notify", () => {
  const dispatcher = mock<JobDispatcher>();
  queue.enqueue({ mrId: "mr-42", platform: "gitlab" });
  expect(dispatcher.notify).toHaveBeenCalled();
});

ReviewFlow example (project-relevant test):

// src/tests/units/entities/reviewScore.test.ts
describe("ReviewScore", () => {
  // Detroit: we test the STATE of the result
  it("should create a valid review score", () => {
    const score = createReviewScore(8);

    expect(score.value).toBe(8);
    expect(score.label).toBe("good");
  });

  // Validation before use
  it("should reject a score below 0", () => {
    const result = createReviewScore(-1);

    expect(result).toBeNull(); // Final state
  });

  // Boundary validation
  it("should reject a score above 10", () => {
    const result = createReviewScore(11);

    expect(result).toBeNull(); // Final state
  });
});

TDD Manifesto

TDD follows these fundamental principles:

PrincipleMeaning
Baby stepsSmall steps for fast and regular feedback
Continuous refactoringWe improve now, not "later"
Evolutionary designWe develop what is necessary and sufficient
Executable documentationTests ARE the living documentation
Minimalist codeSimple and functional > over-dimensioned

Minimal Test Principle

"The simplest thing that could possibly work." — Kent Beck

"As the tests get more specific, the code gets more generic." — Robert C. Martin

Rules:

  1. One behavior per test
  2. From naive to complete: simple case first, edge cases after
  3. No anticipation: one cycle at a time

Typical progression:

Cycle 1: "should create a completion" (nominal case)
Cycle 2: "should have a rating" (property)
Cycle 3: "should reject rating below 1" (validation)
Cycle 4: "should reject rating above 5" (validation)

Anti-pattern:

// Test too broad
it("should validate a completion with rating 1-5 and ISO datetime", () => {
  // tests rating min, max, date format, nominal case...
})

// One behavior per test
it("should create a completion", () => { ... })
it("should reject rating below 1", () => { ... })

Transformation Priority Premise (Robert C. Martin)

The Transformation Priority Premise guides the RED → GREEN transition. When writing minimal code to pass a test, we apply transformations — and these transformations have a natural priority order.

Always choose the highest transformation in the list (the simplest). Skipping steps often leads to suboptimal design.

Transformation list (simplest to most complex)

PriorityTransformationDescriptionExample
1{} → nilNo code → return null/undefinedreturn undefined
2nil → constantReturn a hardcoded valuereturn []
3constant → variableReplace constant with parameterreturn items instead of return []
4unconditional → conditionalAdd a branchif (age < 18) return false
5scalar → collectionGo from single value to arraystring → string[]
6statement → recursion/iterationLoop over the collectionitems.map(transform)
7value → mutated valueTransform the accumulated valueitems.reduce(accumulate)

When to apply

The TPP is a guide, not an absolute rule. It is particularly useful when:

  • Going GREEN seems to require "a lot of code at once" → sign that we're skipping transformations
  • We hesitate between implementations → choose the highest transformation
  • Working on algorithmic logic (parsers, calculations, data transformations, complex validations)

Less relevant for simple orchestration code (call a gateway and return the result).

Concrete example — a presenter formatting tags

// RED: test "should return empty list when no tags"
// GREEN via {} → constant:
return [];

// RED: test "should return formatted tag for single item"
// GREEN via constant → variable:
return [formatTag(tags[0])];

// RED: test "should return formatted tags for multiple items"
// GREEN via scalar → collection + iteration:
return tags.map(formatTag);

If we had jumped directly to map() on the first test, it works — but we would have guessed the design instead of discovering it through tests.

Warning signal

If during GREEN phase you end up writing more than 3-5 lines of code, you're probably skipping transformations. Options:

  1. Go back and add a simpler intermediate test
  2. Check which transformation you're applying in the list

Activation

This skill activates whenever the user asks to touch code:

  • New features: "Implement...", "Add...", "Create..."
  • Bug fixes: "Fix...", "Correct...", "Repair..."
  • Debug: "Why does...", "It doesn't work..."
  • Modifications: "Modify...", "Change...", "Update..."
  • Refactoring: "Refactor...", "Improve...", "Clean up..."

Mandatory Workflow

At each cycle, follow these 3 phases with stop and user validation between each.

Phase RED

Goal: Write ONE failing test

Actions:

  1. Announce: "RED: I will test [specific behavior]"
  2. Identify the smallest possible test (baby step)
  3. Propose the test WITHOUT writing it
  4. Wait for validation
  5. Write the test after validation
  6. Run yarn test:run to confirm failure
  7. Ask: "The test fails as expected. Move to GREEN?"

Template:

RED - Test Proposal

Behavior to test: [description]
File: [path]

Proposed test:
[test code - state-based, verifies the result]

This test verifies that [explanation of expected state].
Validate this test?

Phase GREEN

Goal: Make the test pass with MINIMAL code

Actions:

  1. Announce: "GREEN: I will make the test pass with minimum code"
  2. Propose the minimal implementation WITHOUT writing it
  3. Wait for validation
  4. Write the code after validation
  5. Run yarn test:run to confirm success
  6. Ask: "The test passes. Refactor or next cycle?"

Rules:

  • MINIMAL code that makes the test pass
  • No premature optimization
  • Hardcoded values accepted if sufficient

Template:

GREEN - Implementation Proposal

To make the test pass, I propose:
[minimal code]

This is intentionally minimal because [explanation].
Validate this implementation?

Phase REFACTOR

Goal: Simplify without changing behavior

Principles:

  • KISS: The simplest solution
  • YAGNI: Remove what is not necessary
  • DRY: Factor out only if there is real duplication

Actions:

  1. Announce: "REFACTOR: Analyzing simplification opportunities"
  2. Look for: dead code, premature abstractions, accidental complexity
  3. Propose refactorings one by one
  4. Wait for validation for each
  5. Run yarn test:run after each refactoring
  6. Ask: "Refactor complete. Next RED cycle?"

Priority order: Remove > Simplify > Reorganize

Template:

REFACTOR - Analysis

Code smells detected:
- [smell 1]: [explanation]

Proposed refactoring:
[description of change]

Apply this refactoring?

Special Case: Debug / Bug Fix

  1. Understand: Expected behavior vs actual
  2. RED: Test that reproduces the bug (must fail)
  3. GREEN: Fix so the test passes
  4. REFACTOR: Clean up if necessary

The test becomes a protective regression test.


Mandatory Checkpoints

Never move to the next phase without:

  • Explicit user validation
  • Tests executed and result confirmed

Specs and tickets: no predetermined code

TDD relies on progressive design discovery. Specs/tickets must NOT contain:

ForbiddenWhy
Test namesThe test emerges from the need, not the other way around
File namesArchitecture reveals itself through iteration
Method signaturesDesign comes from the simplest code
Installation commandsDependencies come when necessary

Principle: We don't predict the final code. We proceed by baby steps, from the most naive implementation to the final case.

Ticket with "Tests to implement: should_create_user_with_email"
Ticket with "Files: src/services/user.service.ts"
Ticket with "Method: createUser(email: string): User"

Ticket with Gherkin criteria describing the expected BEHAVIOR

The RED-GREEN-REFACTOR cycle makes the design emerge. The ticket describes the WHAT (behavior), not the HOW (implementation).


Anti-patterns to Block

  • Production code without a red test
  • Multiple tests at once
  • Implementing more than necessary in GREEN
  • Refactoring without green tests
  • Skipping a phase without validation
  • Mocking internal business logic
  • Predetermining code in specs/tickets

End of Cycle

Cycle Complete

Tests added: [number]
Behaviors covered: [list]
Next suggested behavior: [suggestion]

Continue?

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

Guide for creating optimized Claude Code agents. Use to design a new specialized agent, a swarm sub-agent, or a multi-agent workflow. Follows the Skill → Agent (preloaded skills) → Skill orchestration pattern.

日本語の概要は準備中です。原文の説明を表示しています。

DGouron/review-flow442026年10月18日 更新

Anti-overengineering guide based on YAGNI. Use before adding an architectural pattern, during code review, or to challenge an overly complex implementation.

日本語の概要は準備中です。原文の説明を表示しています。

DGouron/review-flow442026年10月18日 更新

Clean Architecture (Uncle Bob) guide for this project. Use when creating modules, entities, use cases, presenters, controllers, gateways, guards, services. Contains tactical patterns and structure conventions.

日本語の概要は準備中です。原文の説明を表示しています。

DGouron/review-flow442026年10月18日 更新

Audit documentation for duplication, staleness, language issues, and verbosity. Read-only — produces an actionable report.

日本語の概要は準備中です。原文の説明を表示しています。

DGouron/review-flow442026年10月18日 更新

Local auto-review of modified code (no GitLab/GitHub). Runs 5 sequential audits and generates a local report. Ideal for validating code before creating a MR/PR.

日本語の概要は準備中です。原文の説明を表示しています。

DGouron/review-flow442026年10月18日 更新

Clean Code (Robert C. Martin) guide to produce and challenge code that is readable, durable, simple, and consistent. Covers naming, functions, comments, smells, and refactor heuristics. Complements `/solid` (SOLID principles) and `/anti-overengineering` (YAGNI/KISS). Activate during the REFACTOR phase of the TDD cycle and during implementation self-review.

日本語の概要は準備中です。原文の説明を表示しています。

DGouron/review-flow442026年10月18日 更新

DGouron のスキルをすべて見る

このスキルの問題を報告する