TDD как поводок для нейросети: пишем тесты, не зная языка
· 3 min read
В конце прошлой статьи наш проект оказался в тупике. Нейросеть втихую подключила парсер абстрактных синтаксических деревьев tree-sitter, превратив кодовую базу в абсолютно нечитаемый для меня «черный ящик».
Мы попытались заставить её откатить изменения, но в сгенерированном коде поползли баги. Поломались зависимости, скрипт перестал запускаться. Оценив масштаб катастрофы, я пришел к простому, но суровому выводу: гораздо проще написать всё с нуля, чем пытаться править архитектурные глюки ИИ, особенно с учетом моего полного незнания Python.
Так наш второй прототип отправился в корзину. Нам нужен был новый подход, который не позволил бы нейросети заниматься самодеятельностью. Этим жестким поводком стала бескомпромиссная связка: детальная формулировка требований и тотальное автоматическое тестирование.

Новый контракт с ИИ
Проблема предыдущих итераций заключалась в том, что мы ставили задачи в духе «распарси этот файл и сделай красиво». Это давало ИИ слишком много свободы.
Чтобы взять архитектуру под контроль, мы полностью изменили формат работы. Теперь перед написанием любой строчки кода мы заключали с нейросетью строгий «контракт». Вот как это выглядело: сначала фиксировались жесткие требования с перечислением допустимых и запрещенных библиотек. Затем ИИ генерировал пошаговый план, который я должен был утвердить. И самое главное — ни одна функция больше не писалась без предварительно созданного автоматического теста.
Как писать тесты, если ты не умеешь кодить?
Тут возникает логичный вопрос: как системный архитектор, который в жизни не написал ни одной строчки на Python, может внедрить Test-Driven Development (TDD)? Ответ прост — тесты тоже пишет ИИ.
Мне не нужно было придумывать сложную логику проверок. Я брал оригинальный XML, который генерировал Doxygen, и находил там нужный фрагмент (например, описание одного класса). Затем я брал красивый, отформатированный HTML-код, который должен был получиться на выходе (тот самый, к которому привыкли разработчики в старой системе).
Я скармливал оба куска в чат и ставил задачу: «Вот XML на входе. Вот готовый HTML, который должен получиться на выходе. Напиши тест, который берет этот XML, прогоняет через наш парсер и проверяет, что строки на выходе посимвольно совпадают с этим HTML».
Нейросеть послушно писала тест с использованием pytest. Естественно, при первом запуске он падал с ошибкой (ведь самого парсера еще не существовало).

Красный. Зеленый. Рефакторинг
Мы взяли классический цикл TDD и слегка адаптировали его под реалии работы с ИИ. Когда тест падал (Красный), нейросеть сама ловила ошибку в консоли и тут же бралась за отладку. Затем наступал Зеленый этап: ИИ молча исправлял код, запускал проверку заново, и тест проходил. Мы получали рабочий кусок кода, делающий ровно то, что заявлено. Наконец, если нейросеть вдруг решала, что алгоритм недостаточно изящен, и пыталась переписать его через регулярные выражения (Рефакторинг), я больше не паниковал. Мы просто снова запускали тесты. Если они зеленые — пусть оптимизирует сколько влезет, а при малейшей красноте мы моментально откатывали изменения.
Магия изоляции
Этот подход сработал безупречно. ИИ оказался строго ограничен нашими требованиями и тестами. Он больше не мог придумывать несуществующие параметры или втихую менять архитектуру, потому что любой шаг в сторону приводил к падению тестов, сравнивающих выходной HTML с эталоном.
Разработка пошла невероятно быстро. Мы покрыли тестами все сценарии (классы, методы, перечисления, параметры). ИИ писал код, сам запускал проверки, и мы планомерно двигались дальше. В итоге у нас на руках оказался идеально работающий движок, который брал громоздкий XML от Doxygen и безупречно превращал его в потрясающе красивые HTML-страницы. Проект можно было смело сдавать в продакшен, если бы не одна неучтенная деталь.

На следующий день к нам пришел Infrastructure Lead и искренне удивился: «А зачем вы до сих пор носитесь с HTML, если есть SSG, от красивого Docusaurus до супермощного Hugo?».
О том, как это одно предложение заставило нас снова переделывать половину проекта, я расскажу в следующей части.