Skip to content
Back to skills

Test Driven Development

ASecurity

Enforce RED-GREEN-REFACTOR discipline for every implementation task. Use for all new features, bug fixes, and refactors. The core rule — if you didn't watch the test fail, you don't know if it tests the right thing.

  • 24 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added October 16, 2026
ai-agentstypescriptgobashtestingapidatabase

Works with

  • api

Security analysis

A100/100

Scanned October 16, 2026

npx -y skills add RBraga01/a-team --skill test-driven-development --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Test Driven Development?

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

Security grade badge for Test Driven Development
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/rbraga01-test-driven-development/badge)](https://www.skillsdirectory.com/skills/rbraga01-test-driven-development)

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: test-driven-development
description: Enforce RED-GREEN-REFACTOR discipline for every implementation task. Use for all new features, bug fixes, and refactors. The core rule — if you didn't watch the test fail, you don't know if it tests the right thing.
---

# Test-Driven Development

## The Core Rule

```
IF YOU DIDN'T WATCH THE TEST FAIL, YOU DON'T KNOW IF IT TESTS THE RIGHT THING.
```

A green test you've never seen red is not a test — it's a decoration.

## The Three Phases (Non-Negotiable)

### Phase RED — Write a Failing Test

Write the test FIRST. Not after. Not "I'll add it later." **First.**

The test must:
- Describe the behavior you want, not the implementation
- Be specific enough to fail for the right reason
- Cover the exact scenario you're about to implement

```typescript
// RED: Write this BEFORE writing the function
test('returns empty array when no users match the filter', () => {
  const result = filterActiveUsers([])
  expect(result).toEqual([])
})
```

**Run it. Watch it fail.**

```bash
npm test -- --testPathPattern="user-filter"
# Expected: FAIL (function doesn't exist yet)
```

If the test passes before you write the implementation: the test is wrong. Rewrite it.

### Phase GREEN — Write Minimal Implementation

Write the **smallest possible code** that makes the test pass. Nothing more.

- No extra features "while I'm here"
- No optimization
- No handling of edge cases not yet covered by tests
- Ugly code that passes is better than beautiful code that doesn't exist yet

```typescript
// GREEN: Minimal implementation that passes the test
function filterActiveUsers(users: User[]): User[] {
  return users.filter(u => u.active)
}
```

**Run it. Watch it pass.**

```bash
npm test -- --testPathPattern="user-filter"
# Expected: PASS
```

If it still fails: read the error message carefully. Fix only what the message tells you.

### Phase REFACTOR — Improve Without Breaking

Now clean up. Rename, extract, simplify — **while keeping tests green**.

```bash
# Run tests continuously during refactor
npm test -- --watch --testPathPattern="user-filter"
```

Rules during refactor:
- Tests must stay green at every step
- No new behavior — only structural improvement
- If tests go red: undo the last change, understand why

## Adding More Tests (Expand-Contract Pattern)

After GREEN for the first case, expand coverage:

```
RED  → watch new test fail
GREEN → minimal code to pass
RED  → add next edge case test
GREEN → handle the edge case
...
REFACTOR → clean up all at once when coverage is complete
```

Cover in order:
1. Happy path (basic success case)
2. Empty / null inputs
3. Boundary values (min, max, exactly-at-limit)
4. Error paths (invalid input, dependency failure)
5. Concurrent / race conditions if applicable

## What to Test vs. What NOT to Test

**Test:**
- Public API surface (exported functions, class methods, HTTP endpoints)
- Business logic decisions
- Data transformations
- Error handling

**Do NOT test:**
- Implementation details (private functions, internal state)
- Third-party library behavior
- Framework internals

## Mocking External Dependencies

External dependencies (database, APIs, file system) must be mocked in unit tests:

```typescript
// Mock the DB before testing the service
jest.mock('../db/users')
const mockFindUser = db.findUser as jest.MockedFunction<typeof db.findUser>
mockFindUser.mockResolvedValue({ id: '1', name: 'Alice', active: true })
```

Integration tests should hit real dependencies — but unit tests must be fast and isolated.

## Coverage Gate

After each feature or bug fix, verify coverage meets the project minimum:

```bash
npm run test:coverage
# Required: ≥ 80% branches, functions, lines, statements
```

If coverage drops below threshold: add tests before moving on.

## TDD Red Flags — You're Doing It Wrong

- Writing the implementation before writing the test
- Running the test only after implementation (never seeing it red)
- Writing tests that test the implementation, not the behavior
- Skipping the refactor phase ("it works, ship it")
- Writing multiple failing tests before making any pass
- Adding edge cases without first making them fail

If you catch yourself rationalizing any of these: stop, revert to the last green state, and start the RED phase properly.

## Integration with A Team Workflow

TDD fits into the full workflow:
1. `brainstorming` → spec approved
2. `writing-plans` → plan with test strategy included
3. **`test-driven-development`** ← you are here, per task
4. `subagent-driven-development` → each subagent runs TDD internally
5. `verification-before-completion` → final proof before claiming done
6. `finishing-a-development-branch` → branch wrap-up

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…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.