Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Tdd

ASecurity

Test-driven development with a red-green-clean loop, running mix credo on the whole project at the end of every vertical slice so standards violations are fixed in the slice that introduced them instead of piling into a refactor at the end. Use when user wants to build features or fix bugs using TDD, mentions "red-green-refactor", wants integration tests, or asks for test-first development.

17 stars
0 votes
0 copies
1 views
Added 9/20/2026
testinggotestingrefactoringapi

Works with

api

Security Analysis

A100/100

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add michaelst/spendable --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 automatically with every re-scan.

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

More formats (shields.io, HTML) on the badges page.

Download with Pro
Files
SKILL.md
---
name: tdd
description: Test-driven development with a red-green-clean loop, running mix credo on the whole project at the end of every vertical slice so standards violations are fixed in the slice that introduced them instead of piling into a refactor at the end. Use when user wants to build features or fix bugs using TDD, mentions "red-green-refactor", wants integration tests, or asks for test-first development.
---

# 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 - "a transaction's unallocated remainder lands in Spendable" 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 functions, or verify through external means (like calling an action module directly instead of the context facade). The warning sign: your test breaks when you refactor, but behavior hasn't changed.

Two rules this codebase enforces that are easy to get wrong:

- **Test through the facade**, never the action module. `Budgets.create_budget/2`, not `Spendable.Budgets.Actions.CreateBudget.create_budget/2`.
- **There are no factories.** Every record a test needs is created through the context function that owns it.

See [tests.md](../../../docs/tests.md) for examples and [mocking.md](mocking.md) for mocking guidelines.

## 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
  ...
```

## Test Economy: Extend Before You Add

Vertical slicing means one behavior per cycle — it does **not** mean one new `test` block per behavior. Before writing a new test, check whether an existing test already establishes the exact setup you need.

**Extend an existing test when** the new behavior shares the same arrange/act and differs only by one assertion or one input value. Add the assertion, or add a case to the existing parametrized list, instead of cloning a whole setup that does mostly the same thing.

**Write a new test when** the behavior needs its own arrange/act, or when folding it into an existing test would obscure which behavior broke on failure.

The goal is to **avoid duplicate scaffolding, not to minimize test count.** A distinct behavior crammed into an unrelated test to save a line is worse than a focused new test — it hurts failure diagnosis and readability. But five near-identical tests that differ by one value should be one test over a list of cases.

## Workflow

### 1. Planning

When exploring the codebase, use the vocabulary the context owns — [CONTEXT-MAP.md](../../../CONTEXT-MAP.md) and the `CONTEXT.md` in the context you are touching — so test names and interface vocabulary match the project's language.

Before writing any code:

- [ ] Confirm with user what interface changes are needed
- [ ] Confirm with user which behaviors to test (prioritize)
- [ ] Identify opportunities for [deep modules](deep-modules.md) (small interface, deep implementation)
- [ ] List the behaviors to test (not implementation steps)

Ask: "What should the public interface look like? Which behaviors are most important to test?"

**Test everything.** Focus testing effort on critical paths and complex logic, then add smaller tests to make sure edge cases are covered. Every action gets the same three at minimum: happy path, domain error, and a scope belonging to another user returning `{:error, :not_authorized}` against the *real* record id.

### 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
CLEAN: mise exec -- mix credo → 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
CLEAN: mise exec -- mix credo → passes
```

Rules:

- One behavior at a time
- Before adding a new test, prefer extending an existing test with matching setup (see [Test Economy](#test-economy-extend-before-you-add))
- Only enough code to pass current test
- Don't anticipate future tests
- Keep tests focused on observable behavior

**Build the setup to exercise the branch, not to pass.** Setup whose defaults make the happy path automatic proves nothing about the path you care about, and the test still goes green — so the bug ships. Before you accept a GREEN, ask what your setup made *impossible*: a transaction whose allocations already sum to its full amount never exercises the Spendable remainder; a budget with no allocations never reaches the balance arithmetic; a Plaid fixture with no pending transactions never reaches `replace_pending`; a scope that owns everything never proves the ownership pin does anything.

When a test passes on the first run, treat it as suspect until you have seen it fail for the right reason.

### 3a. Credo on every slice

**Run `mise exec -- mix credo` at the end of every cycle, once the slice is GREEN.** Not at the end of the feature.

Credo is cheap, and the whole point of running it per slice is that a standards violation caught in the slice that introduced it is a two-line fix. The same violation found after twelve slices is a refactor across everything built on top of it, done at the exact moment you least want to be restructuring code. The custom `SpendableCredo` checks in [credo/](../../../credo) police this codebase's own conventions, so they fire on exactly the things a generic linter would miss.

- **Run it on the whole project**, never with a file filter or path argument. It is fast, and a slice that cleans up its own file while breaking another has not passed.
- **Only fix while GREEN.** Credo runs after the test passes, never while RED — the same rule as refactoring.
- **Fix the underlying issue.** Never edit `credo/.credo.exs` to disable a rule, never add `# credo:disable-for-next-line` or `# credo:disable-for-this-file`, and never delete flagged code purely to silence it.
- **Re-run the test after a credo fix.** A cleanup that breaks the slice you just proved is not done.

This is the same gate [complete-issue](../complete-issue/SKILL.md) runs before commit. Running it per slice means that gate should be green the first time rather than opening a refactor.

### 4. Refactor

After all tests pass, look for [refactor candidates](refactoring.md). Credo has already been satisfied on every slice, so this pass is about the design judgment credo can't see:

- [ ] Extract duplication
- [ ] Ensure code follows the [standards](../../../docs/standards.md)
- [ ] Deepen modules (move complexity behind simple interfaces)
- [ ] Apply SOLID principles where natural
- [ ] Consider what new code reveals about existing code
- [ ] Run tests after each refactor step

**Never refactor while RED.** Get to GREEN first.

## Checklist Per Cycle

```
[ ] Test describes behavior, not implementation
[ ] Test goes through the context facade
[ ] Test creates its data through context functions, not a factory
[ ] Test would survive internal refactor
[ ] Code is minimal for this test
[ ] No speculative features added
[ ] mix credo passes on the whole project
```

Attribution

michaelstmichaelst
View sourceMore from michaelst →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

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 (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Screen Reader Testing

Practical guide to testing web applications with screen readers for comprehensive accessibility validation.

397921 votes

Python Testing

使用pytest、TDD方法、夹具、模拟、参数化和覆盖率要求的Python测试策略。

2456590 votes

Eval Harness

克劳德代码会话的正式评估框架,实施评估驱动开发(EDD)原则

2456590 votes

Tdd Workflow

在编写新功能、修复错误或重构代码时使用此技能。强制执行测试驱动开发,包含单元测试、集成测试和端到端测试,覆盖率超过80%。

2456590 votes

Golang Testing

Go测试模式包括表格驱动测试、子测试、基准测试、模糊测试和测试覆盖率。遵循TDD方法论,采用地道的Go实践。

2456590 votes
View all in testing →