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
BGreen → red → refactor
CСначала весь код, потом все тесты
DRed (падающий тест) → green (минимальный код) → refactor (улучшение)
2. Зачем в TDD писать тест ДО кода?
AЧтобы зафиксировать контракт и убедиться, что тест реально проверяет (виден красным и зелёным)
BЧтобы тестов было больше
CЧтобы ускорить установку Jest
DЭто требование линтера
3. Что обеспечивает безопасность на шаге refactor?
AОтсутствие тестов
BУже зелёные тесты, которые поймают поломку поведения
CУдаление старого кода
DПокрытие 100%