TDD: red-green-refactor

Урок знакомит с разработкой через тесты (TDD) и её циклом из трёх шагов.

TDD (Test-Driven Development) — подход, при котором сначала пишут падающий тест, затем минимальный код, чтобы он прошёл, и только потом улучшают код.

Цикл red-green-refactor

  1. Red — напишите тест на ещё не существующее поведение. Он падает (красный) — это нормально, кода-то нет.
  2. Green — напишите самый простой код, чтобы тест прошёл (зелёный). Можно даже «грубо», без красоты.
  3. Refactor — улучшите код, не ломая тест. Зелёный тест — страховка при чистке.

Затем цикл повторяется для следующего требования.

Почему сначала тест

  • Тест фиксирует требование до реализации — вы думаете о контракте, а не о коде.
  • Гарантирует, что тест действительно проверяет (вы видели его красным и зелёным).
  • Получается ровно столько кода, сколько нужно — без лишнего.
  • Дизайн получается тестируемым по построению.

Проживём цикл на примере

Реализуем isPalindrome по TDD. Сначала тесты падают (функции нет), потом мы её пишем — и они зеленеют. Покажем уже «green»-стадию живьём:

// GREEN: минимальная реализация, прошедшая тесты
function isPalindrome(str) {
  const clean = str.toLowerCase().replace(/[^a-zа-я0-9]/gi, '');
  return clean === clean.split('').reverse().join('');
}

function assert(actual, expected, name) {
  console.log((actual === expected ? '\u2713 passed' : '\u2717 FAILED') +
    ': ' + name);
}

assert(isPalindrome('топот'), true, 'топот — палиндром');
assert(isPalindrome('А роза упала на лапу Азора'), true, 'фраза-палиндром');
assert(isPalindrome('javascript'), false, 'обычное слово — нет');
assert(isPalindrome(''), true, 'пустая строка — палиндром');

Вывод:

✓ passed: топот — палиндром
✓ passed: фраза-палиндром
✓ passed: обычное слово — нет
✓ passed: пустая строка — палиндром

В TDD эти проверки появились бы раньше функции: сначала красные, затем — после написания isPalindrome — зелёные. Потом мы бы спокойно отрефакторили реализацию, опираясь на зелёные тесты.

TDD — инструмент, а не догма

TDD особенно силён для алгоритмов, утилит и сложной логики с понятным контрактом. Для исследовательского кода (ещё не ясно, что строим) или простой вёрстки строгий TDD не обязателен. Главное — суть: думать о поведении и проверяемости заранее.

Итог

  • TDD: red (падающий тест) → green (минимальный код) → refactor (улучшение).
  • Сначала тест — фиксирует контракт и гарантирует, что тест работает.
  • Зелёные тесты страхуют рефакторинг.
  • TDD — инструмент под задачу, особенно хорош для логики и алгоритмов.
Проверьте себя
1. В каком порядке идут шаги цикла TDD?
ARefactor → green → red
BRed (падающий тест) → green (минимальный код) → refactor (улучшение)
CGreen → red → refactor
DСначала весь код, потом все тесты
2. Зачем в TDD писать тест ДО кода?
AЧтобы тестов было больше
BЧтобы зафиксировать контракт и убедиться, что тест реально проверяет (виден красным и зелёным)
CЧтобы ускорить установку Jest
DЭто требование линтера
3. Что обеспечивает безопасность на шаге refactor?
AОтсутствие тестов
BУже зелёные тесты, которые поймают поломку поведения
CУдаление старого кода
DПокрытие 100%
Поддержать проект