> · 7 мин

TDD с Claude Code — как заставить AI писать тесты до кода и перестать ловить баги в продакшене

TDD с Claude Code — как заставить AI писать тесты до кода и перестать ловить баги в продакшене

TDD с Claude Code — как заставить AI писать тесты до кода и перестать ловить баги в продакшене

Claude Code по умолчанию делает ровно то, что делал бы джуниор без присмотра: пишет код, потом — может быть — накидывает пару тестов для галочки. Знакомо? Проблема в том, что AI отлично пишет код, который выглядит рабочим, но ломается на edge cases, которые никто не проверил.

TL;DR: Три способа заставить Claude Code работать по TDD: ручные промпты (бесплатно, ненадёжно), субагенты с изолированным контекстом (надёжно, требует настройки), и плагин tdd-guard (автоматически блокирует код без тестов). По данным F22 Labs, разработчики, использующие TDD с Claude Code, фиксируют 70% меньше багов в продакшене.

Почему Claude Code не делает TDD сам

Вся суть TDD — ты не знаешь реализацию, когда пишешь тест. Тест описывает поведение, а код подстраивается. Но когда Claude Code работает в одном контексте, он видит и тесты, и реализацию одновременно — и начинает подгонять тесты под код, а не наоборот.

Алекс из alexop.dev сформулировал это точно: «LLM не может реально следовать TDD, если все фазы работают в одном контексте — детали реализации загрязняют дизайн тестов».

Три подхода к решению — от простого к надёжному.

Способ 1: Промпты — бесплатно, но дисциплина на тебе

Самый быстрый старт. Добавляешь в CLAUDE.md правила, и Claude Code старается их соблюдать:

# Testing Rules
- Always write failing tests BEFORE implementation
- Run tests to confirm RED state before writing code
- Implementation must ONLY make failing tests pass — no extras
- Never modify tests to make them pass — fix the code

А в сессии используешь конкретные промпты вместо расплывчатых:

# Плохо:
"Добавь тесты для авторизации"

# Хорошо:
"Напиши FAILING тест в tests/auth_test.py для случая logout без активной сессии.
НЕ пиши реализацию. Используй pytest, без моков."

После того как тест написан и упал — второй промпт:

"Напиши минимальную реализацию, чтобы тест прошёл.
НЕ меняй тест. НЕ добавляй фичи сверх того, что тест проверяет."

Проблема: по данным alexop.dev, без автоматизации Claude Code соблюдает TDD-скиллы лишь в ~20% случаев. Он «забывает» правила через 5-6 промптов, особенно в длинных сессиях.

Способ 2: Три субагента — каждый знает только своё

Самый элегантный подход — разделить red-green-refactor на три изолированных субагента. Каждый работает в своём контексте и физически не видит то, что делают остальные.

Агент 1 — tdd-test-writer (фаза RED):

# .claude/agents/tdd-test-writer.md
---
description: Writes failing tests for new features
tools: Read, Glob, Grep, Write, Edit, Bash
---

You write integration tests that MUST FAIL when run.
- Read existing code to understand interfaces
- Write tests that describe DESIRED behavior, not current
- Run tests and confirm failure
- Return: test file path, failure output, behavior summary

NEVER write implementation code. NEVER stub return values.

Агент 2 — tdd-implementer (фаза GREEN):

# .claude/agents/tdd-implementer.md
---
description: Minimal implementation to pass tests
tools: Read, Glob, Grep, Write, Edit, Bash
---

You write ONLY the code needed to make failing tests pass.
- Read test files to understand expected behavior
- Write minimal implementation
- Run tests and confirm they pass
- Return: modified files, test output

NEVER modify test files. No extras, no "nice to haves."

Агент 3 — tdd-refactorer (фаза REFACTOR):

# .claude/agents/tdd-refactorer.md
---
description: Improves code quality while keeping tests green
tools: Read, Glob, Grep, Write, Edit, Bash
---

Evaluate: duplication, naming, component thickness, reusability.
If code is clean — return "No refactoring needed" with reasoning.
After changes — run tests, confirm green.

Оркестрация — через скилл, который вызывает агентов последовательно:

# .claude/skills/tdd/SKILL.md

1. Call tdd-test-writer → get failing test
2. STOP if test doesn't fail — something wrong
3. Call tdd-implementer → get passing code
4. STOP if tests don't pass — fix before proceeding
5. Call tdd-refactorer → optional cleanup
6. Commit with descriptive message

Каждый субагент изолирован: test-writer не видит план реализации, implementer не может поменять тесты. Это и есть настоящий TDD.

Способ 3: tdd-guard — плагин, который блокирует нарушения

tdd-guard — open-source плагин, который использует хуки Claude Code для перехвата изменений файлов. Если ты пытаешься написать код без failing теста — он буквально останавливает Claude и объясняет, что нужно сделать сначала.

Установка за три команды:

/plugin marketplace add nizos/tdd-guard
/plugin install tdd-guard@tdd-guard
/tdd-guard:setup

Что он блокирует:

  • Код без теста — нельзя написать реализацию, пока нет falling теста
  • Перереализацию — нельзя писать больше, чем требуют текущие тесты
  • Пропуск рефакторинга — lint-интеграция напоминает про cleanup

Поддерживает Vitest, Jest, pytest, PHPUnit, Go test, Rust — так что работает практически для любого стека. Требует Node.js 22+.

Бонус: хук для принудительной активации скиллов

По данным alexop.dev, одна из главных проблем — Claude «забывает» про TDD-скиллы даже когда они настроены. Решение — хук UserPromptSubmit, который перед каждым промптом заставляет Claude оценить, какие скиллы нужны:

{
  "hooks": {
    "UserPromptSubmit": [{
      "matcher": "",
      "hooks": [{
        "type": "command",
        "command": "npx tsx .claude/hooks/user-prompt-skill-eval.ts"
      }]
    }]
  }
}

Хук инжектит в каждый промпт инструкцию: «Сначала оцени — нужен ли TDD-скилл? Да/нет и почему». По замерам автора, это подняло активацию скиллов с ~20% до ~84% — проверено на 200+ промптах.

Подводные камни

1. Субагенты дороже одиночной сессии. Три агента = три контекстных окна = примерно 3× расход токенов на фичу. Для Max-плана это терпимо, для Pro — ощутимо. Совет: запускай субагентов на Sonnet через model: sonnet в frontmatter, а оркестратор оставляй на Opus.

2. tdd-guard требует Node.js 22+. Если проект на Python или Go и Node не установлен — придётся ставить только ради плагина. Для чисто Python-проекта проще субагенты.

3. Длинные интеграционные тесты убивают цикл. Если один прогон тестов занимает 30+ секунд, red-green-refactor превращается в red-wait-green-wait-refactor-wait. Выход — запускай только изменённые тесты: pytest tests/test_auth.py::test_logout -x вместо полного pytest.

4. Claude иногда «подглядывает». Даже с субагентами, если test-writer имеет доступ к Read и может прочитать существующую реализацию — изоляция неполная. Для максимальной чистоты ограничивай test-writer'у доступ только к тестовым файлам и интерфейсам.

5. Рефакторинг-агент может «улучшить» рабочий код до нерабочего. Если рефакторер слишком агрессивен, он выносит логику в абстракции, которые ломают следующие тесты. Добавь в его инструкции: «Если сомневаешься — верни 'No refactoring needed'».

Вердикт

Из трёх подходов субагенты дают самый надёжный TDD — физическая изоляция контекста решает главную проблему AI, которая заключается в подгонке тестов под код. tdd-guard — лучший выбор для тех, кто не хочет писать агентов вручную, но готов поставить Node.js 22. Промпты в CLAUDE.md работают лишь как напоминание, а не как enforcement.

Реалистичный эффект: не 70% меньше багов (эта цифра предполагает идеальное следование), а скорее 30-40% — потому что на практике ты будешь пропускать рефакторинг-фазу и иногда «разрешать» Claude дописать чуть больше, чем нужно. Но даже 30% — это разница между «опять пятница с хотфиксом» и «спокойный деплой».

Как попробовать

  1. Минимальный старт: добавь в CLAUDE.md четыре правила из «Способа 1» — это занимает 30 секунд
  2. Установи tdd-guard: три команды выше, 2 минуты — и Claude Code физически не сможет пропустить тесты
  3. Попробуй промпт: "Напиши FAILING тест для [твоя фича]. НЕ пиши реализацию. Запусти тест и покажи, что он падает."
  4. Для продвинутых: создай три субагента из «Способа 2» — настройка ~2 часа, но потом каждая фича идёт по рельсам
  5. Документация: Claude Code Best Practices, tdd-guard на GitHub, полный гайд alexop.dev
$ ls ./related/

Похожие статьи

subscribe.sh

$ cat /dev/blog/updates

> Свежие заметки о программировании,

> DevOps и AI — прямо в мессенджер

./subscribe