Vertical Slice TDD with Tracer Bullets

Build features one tested behavior at a time, starting with a tracer bullet that proves the required path works.

Development / Testingtddvertical-slices
by AgentVoltv1.0.0
Free to sign up · every skill included with AgentVolt Pro

Before & after

Same prompt, same agent — the only difference is the skill.

Prompt“Write a new authentication feature using test-driven development with vertical slices”
Beforegeneric AI agent
For TDD, you'd normally write tests first before implementing the code. You could start with a failing test and then write code to make it pass. Vertical slices mean building small, complete features rather than layers. That's generally a good approach. You might need to decide what framework to use for testing. Would it be better to start with unit tests, integration tests, or end-to-end tests? And should I write all the tests first or add them as I go?
Afterwith Vertical Slice TDD with Tracer Bullets
TDD VERTICAL SLICE: OAuth2 Token Refresh

TRACER BULLET 1: END-TO-END TEST (Red)
Write test first, no implementation:

test('POST /auth/refresh returns new access token with valid refresh token', async () => {
  const refreshToken = 'old_refresh_token_expires_2026_08_31';
  const response = await client.post('/auth/refresh', { refreshToken });
  expect(response.status).toBe(200);
  expect(response.body.accessToken).toBeDefined();
  expect(response.body.expiresIn).toBe(3600);
});

Run test: FAILS (no POST /auth/refresh endpoint)

TRACER BULLET 2: MINIMAL IMPLEMENTATION (Green)
Write only enough code to pass test:

app.post('/auth/refresh', (req, res) => {
  res.json({ accessToken: 'dummy_token', expiresIn: 3600 });
});

Run test: PASSES (test is now green)

TRACER BULLET 3: ITERATE (Refactor)
Add next test for edge case:

test('POST /auth/refresh returns 401 with expired refresh token', async () => {
  const expiredToken = 'old_refresh_token_expires_2026_07_30';
  const response = await client.post('/auth/refresh', { refreshToken: expiredToken });
  expect(response.status).toBe(401);
  expect(response.body.error).toBe('Refresh token expired');
});

Run test: FAILS (token validation not implemented)

Add validation logic:

app.post('/auth/refresh', (req, res) => {
  const { refreshToken } = req.body;
  const decoded = jwt.verify(refreshToken, SECRET); // Throws if expired
  if (decoded.exp < Date.now() / 1000) {
    return res.status(401).json({ error: 'Refresh token expired' });
  }
  const newToken = jwt.sign({ userId: decoded.userId }, SECRET, { expiresIn: '1h' });
  res.json({ accessToken: newToken, expiresIn: 3600 });
});

Run test: PASSES

TRACER BULLET 4: NEXT VERTICAL SLICE
Don't build adjacent features yet (persistence layer, UI, etc.)
Instead, write next end-to-end test for next slice:

test('POST /auth/refresh increments token version (prevent replay attacks)', ...);
test('POST /auth/refresh logs revocation event to audit table', ...);

Each test spawns its own implementation. Build width (features) incrementally, not depth (layers).

WHY THIS WORKS
• Tests remain always-passing (no broken tests accruing)
• Each feature complete and tested before next starts
• No large refactors at the end (refactoring happens per-slice)
• Easy to show progress ("3 features passing" vs "infrastructure 80% done")

WHEN TO STOP SLICING
Stop when:
✓ All user-facing flows have passing tests
✓ Happy path + 2-3 error cases per feature
✓ No more than 20 lines per test function (if test >20 lines, feature too big)

About this skill

Your tests pass, but the feature still doesn't work across its layers. Or the implementation grows for hours before anything runs. This workflow starts with a tracer bullet that proves one useful path, then expands it through small, verified test-first changes.

What it does

  • Turns a feature request into observable behaviors ordered by dependency and integration risk.
  • Chooses a first test that crosses the boundaries the feature actually needs.
  • Distinguishes an expected behavior failure from a broken test harness or missing dependency.
  • Keeps each cycle to one failing behavior and the smallest implementation that satisfies it.
  • Uses real internal collaborators while isolating external services at their adapters.
  • Records what each test proves, which checks ran, and what remains unverified.

What you get

An incrementally implemented feature or bug fix, with regression tests and concise verification evidence. For planning or review requests, you get a concrete first slice and an ordered progression of testable behaviors.

Best for

Developers using Claude Code to build features, repair bugs, or recover from speculative implementations that passed isolated tests but failed when connected.

SKILL.md preview

SKILL.md
---
name: vertical-slice-tdd-with-tracer-bullets
description: >-
  Build features through vertical slices: prove one thin path across required boundaries, then add one behavior per observed red-green-refactor cycle. Use when the user says "build this test first", "add this feature with TDD", "my tests pass but the feature doesn't work", "we built too much before testing", "start with a tracer bullet", "fix this bug with a regression test", or "review our TDD approach".
---

# Vertical Slice TDD with Tracer Bullets

… (sign up to view the full skill)
Sign up to view, copy, and install the full skill

More development skills

View all Development skills →