Главная  /  Статьи  /  TDD

TDD-цикл с Vibe Codex: красный, зелёный, рефакторинг

Лучший AI-ассистент для TDD — тот, который сначала признаётся, что тест падает, и только потом предлагает решение.

TDD страдает от той же болезни, что и большая часть инженерных практик: «теоретически — да, на проекте — некогда». Vibe Codex меняет расклад: цикл «красный → зелёный → рефакторинг» проходится за три-пять минут вместо двадцати, и поэтому фактически делается.

Красный: формализуем поведение

TDD начинается не с теста, а с описания: «что должно произойти?». Пока есть устная формулировка, теста ещё нет.

$ vibe-codex tdd "функция normalizePhoneRu принимает строку, \
                  возвращает E.164 для российских номеров; \
                  если не получается — null"

Ассистент уточняет:

[opus] Уточнения:
  - +7XXXXXXXXXX и 8XXXXXXXXXX — оба валидные?
  - пробелы, скобки, дефисы — игнорировать?
  - короткие номера (112, 911) — null или ошибка?
  - КZ-номера (+77XXXXXXXX) — null (не российские)?
[me]    да / да / null / null
[opus] ок, генерирую тесты.
// pkg/phone/phone_test.go
func TestNormalizePhoneRu(t *testing.T) {
    cases := []struct {
        in, want string
    }{
        {"+79161234567",        "+79161234567"},
        {"89161234567",         "+79161234567"},
        {"+7 (916) 123-45-67",  "+79161234567"},
        {"8 916 123 45 67",     "+79161234567"},
        {"112",                 ""},   // null
        {"abc",                 ""},   // null
        {"+77011234567",        ""},   // KZ, null
    }
    for _, tc := range cases {
        if got := NormalizePhoneRu(tc.in); got != tc.want {
            t.Errorf("for %q got %q, want %q", tc.in, got, tc.want)
        }
    }
}
$ go test ./pkg/phone
FAIL    ./pkg/phone     [build failed]

Идеально. Тест падает — потому что функции ещё нет.

Зелёный: минимальная реализация

Хороший ассистент знает, что «минимальная» — это буквально минимальная. Не «правильная архитектурно», а «делает тесты зелёными».

$ vibe-codex tdd green
[opus] Генерирую минимальную реализацию:
       - удаляем не-цифры
       - проверяем длину 11 и первую цифру
       - заменяем 8 на 7
[written] pkg/phone/phone.go
package phone

import "strings"

func NormalizePhoneRu(in string) string {
    digits := strings.Map(func(r rune) rune {
        if r >= '0' && r <= '9' {
            return r
        }
        return -1
    }, in)

    if len(digits) != 11 {
        return ""
    }
    if digits[0] == '8' {
        digits = "7" + digits[1:]
    }
    if digits[0] != '7' {
        return ""
    }
    return "+" + digits
}
$ go test ./pkg/phone
PASS
ok      ./pkg/phone     0.012s

Рефакторинг: имя, структура, инварианты

Здесь ассистент делает то, что обычно скучно: вынести магические числа, добавить комментарии где это правда нужно, проверить читаемость.

$ vibe-codex tdd refactor
[opus] Предложения:
  - вынести len(digits) != 11 в константу phoneLen
  - выделить isDigit в отдельную функцию или использовать
    unicode.IsDigit
  - добавить doc-comment на функцию

[diff] +12 -8

Заметьте — рефактор маленький. Это правильно: большой рефакторинг ломает фокус.

Где TDD-цикл ломается без аккуратности

«Самая лёгкая ошибка — попросить ассистент сделать „красный→зелёный“ одной командой. На выходе вы получите тест, написанный под уже существующую реализацию».

Багфикс по TDD

Это любимый кейс. Пришёл баг — пишем тест, который его воспроизводит:

$ vibe-codex tdd bug "после ребута сервиса баланс пользователя \
                      показывается на 100 рублей меньше"
[opus] Гипотезы:
   1) кеш не сбрасывается;
   2) транзакция баланса не зафиксирована до рестарта;
   3) round() в одном месте — round(), в другом — floor().
[opus] Какую проверить первой?

Это не «AI сам нашёл баг». Это «AI помог сформулировать гипотезы, чтобы вы их проверили».

Когда TDD не работает

В UI с тонкой моторикой пикселей, в перформанс-критичном коде, в исследовательских скриптах. Vibe Codex знает эти зоны и сам предлагает другой подход — характеристические тесты, бенчмарки, проверка глазами.

Скучный итог

TDD — это дисциплина, которую обычно бросают, потому что «долго». Vibe Codex делает её быстрой ровно настолько, чтобы перестать бросать. Это не магия — это снятый барьер. Дальше всё зависит от вас.

Готов попробовать?

brew tap xrouter-chat/tap && brew install vibe-codex — и за 30 секунд ты в деле.

Поставить Vibe Codex →