TDD как поводок для нейросети: пишем тесты, не зная языка

 · 3 min read

В конце прошлой статьи наш проект оказался в тупике. Нейросеть втихую подключила парсер абстрактных синтаксических деревьев tree-sitter, превратив кодовую базу в абсолютно нечитаемый для меня «черный ящик».

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

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

Контракт с ИИ

Новый контракт с ИИ

Проблема предыдущих итераций заключалась в том, что мы ставили задачи в духе «распарси этот файл и сделай красиво». Это давало ИИ слишком много свободы.

Чтобы взять архитектуру под контроль, мы полностью изменили формат работы. Теперь перед написанием любой строчки кода мы заключали с нейросетью строгий «контракт». Вот как это выглядело: сначала фиксировались жесткие требования с перечислением допустимых и запрещенных библиотек. Затем ИИ генерировал пошаговый план, который я должен был утвердить. И самое главное — ни одна функция больше не писалась без предварительно созданного автоматического теста.

Как писать тесты, если ты не умеешь кодить?

Тут возникает логичный вопрос: как системный архитектор, который в жизни не написал ни одной строчки на Python, может внедрить Test-Driven Development (TDD)? Ответ прост — тесты тоже пишет ИИ.

Мне не нужно было придумывать сложную логику проверок. Я брал оригинальный XML, который генерировал Doxygen, и находил там нужный фрагмент (например, описание одного класса). Затем я брал красивый, отформатированный HTML-код, который должен был получиться на выходе (тот самый, к которому привыкли разработчики в старой системе).

Я скармливал оба куска в чат и ставил задачу: «Вот XML на входе. Вот готовый HTML, который должен получиться на выходе. Напиши тест, который берет этот XML, прогоняет через наш парсер и проверяет, что строки на выходе посимвольно совпадают с этим HTML».

Нейросеть послушно писала тест с использованием pytest. Естественно, при первом запуске он падал с ошибкой (ведь самого парсера еще не существовало).

Цикл TDD

Красный. Зеленый. Рефакторинг

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

Магия изоляции

Этот подход сработал безупречно. ИИ оказался строго ограничен нашими требованиями и тестами. Он больше не мог придумывать несуществующие параметры или втихую менять архитектуру, потому что любой шаг в сторону приводил к падению тестов, сравнивающих выходной HTML с эталоном.

Разработка пошла невероятно быстро. Мы покрыли тестами все сценарии (классы, методы, перечисления, параметры). ИИ писал код, сам запускал проверки, и мы планомерно двигались дальше. В итоге у нас на руках оказался идеально работающий движок, который брал громоздкий XML от Doxygen и безупречно превращал его в потрясающе красивые HTML-страницы. Проект можно было смело сдавать в продакшен, если бы не одна неучтенная деталь.

Сюрприз от инфраструктуры

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

О том, как это одно предложение заставило нас снова переделывать половину проекта, я расскажу в следующей части.