November 29, 2025 (10mo ago) — last updated September 9, 2026 (1mo ago)

TDD: Red‑Green‑Refactor — практическое руководство

Освойте цикл Red‑Green‑Refactor в TDD: рабочий процесс, пример на React/TypeScript и практические советы по внедрению для повышения качества и предсказуемости.

← Back to blog
Cover Image for TDD: Red‑Green‑Refactor — практическое руководство

Цикл Red‑Green‑Refactor в TDD помогает превращать большие задачи в маленькие проверяемые шаги: сначала проваливающийся тест, затем минимальная реализация и, наконец, рефакторинг. Такой подход повышает качество, снижает риски и делает поведение кода понятным для команды.

TDD: Red‑Green‑Refactor — практическое руководство

Краткое содержание: Освойте цикл Red‑Green‑Refactor в разработке через тестирование (TDD) с практическим рабочим процессом, примером на React/TypeScript и аргументами по внедрению в команду, чтобы создавать более чистый и сопровождаемый код.

Введение

Цикл Red‑Green‑Refactor в Test‑Driven Development (TDD) — это дисциплинированный рабочий процесс, который превращает большие задачи в маленькие проверяемые шаги. Сначала пишете проваливающийся тест (Red), затем минимальную реализацию для прохождения теста (Green), и наконец — улучшаете код, не меняя его поведение (Refactor). Такой подход повышает качество, снижает риски и делает намерения кода понятными для команды1.

Что такое Red‑Green‑Refactor

TDD — это прежде всего практика проектирования: тесты пишутся первыми, чтобы задать публичное поведение до реализации. Это уменьшает домыслы, поощряет маленький целенаправленный прогресс и делает разработку предсказуемой.

Три этапа и их цель

  • Фаза Red (проваливающийся тест): опишите минимальное полезное поведение с помощью автоматизированного теста. Тест должен падать — это подтверждает корректность требования.
  • Фаза Green (проход теста): реализуйте минимальный объём кода, чтобы тест прошёл. Ставьте простоту выше изящества, чтобы избежать чрезмерной инженерии.
  • Фаза Refactor (улучшение кода): с тестами как страховочной сеткой уберите дублирование, улучшите имена и структуру, не меняя поведение.

Пропуск шага рефакторинга накапливает технический долг и усложняет будущие изменения.

Быстрая сводка

ФазаЦельЗадача разработчика
RedЗадать требование и подтвердить тестНаписать один маленький тест, который падает
GreenУдовлетворить требованиеДобавить минимальный код для прохождения теста
RefactorУлучшить внутреннее качествоУбрать дублирование и прояснить намерение

Принятие этого ритма помогает командам двигаться уверенно и предсказуемо. Модель внедрения варьируется по организациям и рынкам1.

Практический пример: LikeButton (React + TypeScript + Jest)

Ниже пошаговый пример, который показывает, как TDD направляет дизайн UI‑компонента.

Red‑Green‑Refactor TDD cycle

Фаза Red: первое требование

Самое простое требование: компонент рендерится без ошибок и отображает “Like”. Пишем тест до компонента.

// LikeButton.test.tsx
import React from "react";
import { render, screen } from "@testing-library/react";
import LikeButton from "./LikeButton";

describe("LikeButton", () => {
  it("renders a button with the initial text “Like”", () => {
    render(<LikeButton />);
    const likeButton = screen.getByRole("button", { name: /like/i });
    expect(likeButton).toBeInTheDocument();
  });
});

Запуск теста завершается неудачей, потому что компонента ещё нет — это ожидаемая фаза Red.

Фаза Green: минимальная реализация

Создайте минимальный компонент, чтобы удовлетворить тест.

// LikeButton.tsx
import React from "react";

const LikeButton = () => {
  return <button>Like</button>;
};

export default LikeButton;

Запустите тесты снова — они проходят. Задача этого цикла выполнена.

Фаза Refactor: добавить типы и шаблон

Улучшаем код, добавляя типы и шаблон для расширения.

// LikeButton.tsx (refactored)
import React, { FC } from "react";

type LikeButtonProps = {};

const LikeButton: FC<LikeButtonProps> = () => {
  return <button>Like</button>;
};

export default LikeButton;

Тесты по‑прежнему проходят. Страховая сетка позволяет безопасно улучшать реализацию.

Итерация: поведение при клике

Новое требование: при клике текст меняется на “Liked”, и кнопка становится отключённой. Сначала тест, затем реализация.

// LikeButton.test.tsx
it('changes text to “Liked” and becomes disabled when clicked', () => {
  render(<LikeButton />);
  const likeButton = screen.getByRole("button", { name: /like/i });
  fireEvent.click(likeButton);
  expect(likeButton).toHaveTextContent("Liked");
  expect(likeButton).toBeDisabled();
});

Реализуем минимальное поведение, чтобы пройти тест.

// LikeButton.tsx
import React, { FC, useState } from "react";

type LikeButtonProps = {};

const LikeButton: FC<LikeButtonProps> = () => {
  const [liked, setLiked] = useState(false);
  const handleClick = () => setLiked(true);
  return (
    <button onClick={handleClick} disabled={liked}>
      {liked ? "Liked" : "Like"}
    </button>
  );
};

export default LikeButton;

Запустите тесты — всё зелёное. Повторяйте: одно маленькое требование за раз, защищённое тестами.

Бизнес‑основание: почему это важно

Инженерные преимущества TDD переводятся в бизнес‑ценность. Меньше дефектов в продакшене означает ниже затраты на поддержку, меньший отток клиентов и крепче репутация бренда. Когда дефекты ловят рано, их исправление обходится дешевле, а команды могут тратить больше времени на новые функции2.

Исследования и отчёты показывают измеримые улучшения качества и сокращение усилий на отладку при дисциплинированном использовании TDD и автоматизированного тестирования в CI23. Нехватка адекватного тестирования приводит к существенным экономическим потерям в масштабе отрасли5.

Снижение дефектов и затрат на поддержку

Пишете тесты перед кодом — и добавляете в продакшн только необходимый код. Это создаёт надёжную страховочную сетку и снижает регрессии. Исследования, включая контролируемые эксперименты, показывают положительное влияние TDD на качество кода и снижают количество дефектов в ряде случаев2.

Ускорение онбординга и предсказуемость

Набор тестов служит как исполняемая документация. Новые разработчики могут запускать тесты, чтобы понять ожидаемое поведение системы, вместо того чтобы полагаться на устаревшие вики. Последовательные практики TDD повышают предсказуемость релизов и улучшают коммуникацию со стейкхолдерами3.

Распространённые ловушки и как их избегать

TDD легко описать, но сложно освоить. Ниже типичные анти‑паттерны и способы их предотвращения.

1. Интеграционные тесты, замаскированные под юнит‑тесты

Проблема: тест затрагивает много компонентов и внешних зависимостей. Решение: тестируйте один модуль в изоляции с помощью моков, стабов и фейков. Отдельно пишите интеграционные тесты для проверки взаимодействия компонентов4.

2. Тестирование реализации вместо поведения

Проблема: тесты проверяют внутренние детали, а не публичное поведение. Решение: тестируйте то, что видит и делает пользователь. Тесты, ориентированные на поведение, устойчивы к рефакторингу и служат документацией.

3. Пропуск рефакторинга

Проблема: после того как тесты проходят, разработчики сразу переходят к следующей фиче. Решение: рассматривайте рефакторинг как обязательный этап. Небольшие улучшения после Green удерживают кодовую базу в хорошем состоянии.

Интеграция TDD в команду и работа с унаследованным кодом

Принятие TDD — это техническое и культурное изменение. Сделайте тесты частью Definition of Done и поощряйте обучение в команде.

Как продвигать TDD внутри команды

  • Парное программирование, где опытный разработчик проводит коллегу через цикл Red‑Green‑Refactor.
  • Mob‑программирование для сложных задач с ротацией ведущего.
  • Lunch‑and‑learn сессии, демонстрирующие реальные примеры TDD в вашей кодовой базе.

Начинайте с одной новой фичи или некритичного бага и расширяйте практику постепенно.

Работа с унаследованным кодом

Пишите characterization tests, чтобы зафиксировать текущее поведение перед изменениями. Это снизит риск при рефакторинге и добавлении новых фич.

Автоматизация с CI/CD

Запускайте тесты при каждом коммите в CI. Автоматизация даёт немедленную обратную связь и делает прохождение тестов обязательным шагом перед слиянием. Интеграция TDD и CI повышает скорость и качество доставки — настройте сборку так, чтобы тесты были быстрыми и надёжными3.

Частые вопросы — подробные ответы

Заменяет ли TDD другие виды тестирования?

Нет. TDD фокусируется на юнит‑тестах как инструменте проектирования, но по‑прежнему нужны интеграционные и end‑to‑end тесты для проверки взаимодействия компонентов и полных пользовательских сценариев.

Как использовать TDD с базами данных или внешними API?

Изолируйте зависимости с помощью моков, стабов или фейков. Тестируйте логику в «пузыре», а реальные интеграционные тесты запускайте отдельно в CI.

Стоит ли тестировать простые UI‑компоненты?

Да, если тесты проверяют поведение, а не реализацию. Проверяйте то, что видит и делает пользователь: отображение меток, доступность и реакции на события.

Краткие Q&A (быстрый справочник)

В: Через какое время команда увидит выгоду от TDD?

А: Выгоды начинают проявляться уже через несколько спринтов при дисциплинированном применении — меньше регрессий и быстрее локализация багов2.

В: Какой первый шаг при внедрении TDD?

А: Начните с одной новой фичи или некритичного бага: требуйте проваливающийся тест перед реализацией и настаивайте на шаге рефакторинга.

В: Как доказать ценность тестов заинтересованным лицам?

А: Покажите уменьшение инцидентов в продакшене, снижение затрат на исправления и примеры ускоренной доставки фич. Отчёты и исследования подтверждают экономическую пользу автоматизированного тестирования и дисциплин разработки23.

Внутренние ссылки для дальнейшего чтения

1.
Digital.ai, “State of Agile Report,” Digital.ai, https://digital.ai/resource-center/state-of-agile-report
2.
Basili, Victor R., et al., “An Empirical Study on the Effects of Test-Driven Development,” https://link.springer.com/article/10.1007/s10664-015-9378-2
3.
Google Cloud, “State of DevOps Report,” https://cloud.google.com/devops/state-of-devops
4.
Martin Fowler, “TestDrivenDevelopment,” https://martinfowler.com/bliki/TestDrivenDevelopment.html
5.
NIST, “The Economic Impacts of Inadequate Infrastructure for Software Testing,” National Institute of Standards and Technology, https://www.nist.gov/publications/economic-impacts-inadequate-infrastructure-software-testing
← Back to blog
🙋🏻‍♂️

ИИ пишет код.
Вы делаете его долговечным.

В эпоху ускорения ИИ чистый код — это не просто хорошая практика — это разница между системами, которые масштабируются, и кодовыми базами, которые рушатся под собственным весом.