Перейти к содержанию
Публикация AiManual

Тесты для кодинг-агентов: почему TDD проиграл дифференциальному тестированию

Дэн Лу прогнал агента на GPT-6 Astra через 25 техник тестирования и потратил около $90 тысяч: TDD дал 40,5% полностью успешных прогонов, дифференциальное тестир

Коротко

Что будет в материале

  1. 01

    Что показал эксперимент Дэна Лу: короткий ответ

  2. 02

    Как устроен эксперимент: задача, метрика и почему Pandoc

  3. 03

    TDD, дифференциальное тестирование и Default: цифры и что за ними стоит

  4. 04

    Почему вывод «тесты от ИИ доказанно бесполезны» неверен

Что показал эксперимент Дэна Лу: короткий ответ

Дэн Лу (Dan Luu) дал агенту на GPT-6 Astra одну задачу: написать Pandoc. В каждом из 25 условий менялось ровно одно, формулировка о том, как тестировать код. Каждое условие прогонялось 25 раз, весь забег обошёлся примерно в 90 тысяч долларов по розничным ценам API.

Мерили не скорость и не красоту кода, а долю прогонов, где агент прошёл все скрытые тесты целиком. Итог: TDD дал 40,5% полностью успешных прогонов, дифференциальное тестирование 45,1%, условие без указаний по тестированию (Default) 44,1%.

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

Как устроен эксперимент: задача, метрика и почему Pandoc

Дизайн ближе к A/B-тесту, чем к бенчмарку. Задача одна, модель одна, агентский каркас один, меняется только инструкция про тестирование. 25 условий умножить на 25 прогонов дают 625 запусков агента на одной и той же задаче.

Метрика жёсткая: прогон считается успешным, только если пройдены все скрытые тесты полностью. Частичный успех не засчитывается, поэтому проценты ниже, чем в отчётах вида «столько-то тестов пройдено». Скрытые тесты агентам не показывают, и это принципиальная часть схемы. Исходный разбор с цифрами по всем условиям и оговорками автора опубликован отдельно: перевод материала Дэна Лу на Habr.

Формулировки условий различались по типу тестирования: TDD, дифференциальное сравнение с эталоном, property-based подход, формальная верификация, фаззинг, отсутствие инструкций. Всё остальное, включая модель и уровень усилий, держали фиксированным, иначе сравнение потеряло бы смысл.

Почему скрытые тесты, а не тесты, которые пишет сам агент

Агент, который пишет и код, и тесты к нему, легко замыкает систему на себя: тесты проверяют то, что код делает, а не то, что он должен делать. Получается зелёный CI и сломанное поведение на реальных входных данных.

Внешний набор тестов ломает эту петлю. Он не виден агенту, подгонять под него нечего, и остаётся один путь: разбираться в поведении по документации и закрывать края. Похожая логика лежит в паттерне верификации LLM-агентов, где результат подтверждают независимые воспроизводимые проверки, а не самоотчёт модели: архитектура LLM-агентов с верификацией.

Почему Pandoc - сложная, но показательная задача

Pandoc конвертирует документы между десятками форматов разметки, и почти каждый формат приносит свои граничные случаи: вложенные структуры, экранирование, юникод, неоднозначные конструкции. Ошибиться в мелочи легко, а проверяется поведение на живых документах, а не набор функций.

Такая задача чувствительна к тому, насколько глубоко агент разбирает края, и потому неплохо разделяет техники тестирования. Одна задача всё равно не даёт универсального вывода: в том же цикле экспериментов на Zstd и IMAP картина другая, и к ней мы вернёмся.

TDD, дифференциальное тестирование и Default: цифры и что за ними стоит

УсловиеДоля полностью успешных прогонов на скрытых тестах
TDD40,5%
Дифференциальное тестирование45,1%
Default (без указаний по тестированию)44,1%

Арифметика простая. TDD отстал от лидера на 4,6 процентного пункта, от условия без инструкций на 3,6. Дифференциальное тестирование обошло Default всего на 1 процентный пункт.

Главный неудобный факт в том, что Default, где агенту вообще не говорили, как тестировать, обошёл TDD и почти догнал победителя. Точные проценты по всем 25 условиям и авторские оговорки к ним собраны в исходном разборе эксперимента. При 25 прогонах на условие разница в несколько процентных пунктов не тянет на доказательство превосходства одной техники над другой, это повод проверить гипотезу в своём проекте.

Почему TDD оказался в хвосте

Рабочая интерпретация из материала такая: TDD требует сначала написать тесты, и агент фиксирует в них своё текущее, ещё не проверенное понимание задачи. Дальше код подгоняется под эти ожидания, включая ошибочные, а узкий набор кейсов закрывает не всё поведение.

За доказанный факт это выдавать не стоит, автор сам не абсолютизирует вывод. Косвенный довод в ту же сторону нашёлся в предыдущем эксперименте на Zstd с GPT-5.6 Sol: просьбы тестировать определённым способом в основном делали результат хуже, а отсутствие инструкций оказалось одним из лучших условий.

Почему дифференциальное тестирование выиграло

Дифференциальное тестирование сравнивает поведение новой версии с эталоном на одних и тех же входах: тот же документ прогоняется через старую и новую версию, результат сверяется. Расхождение указывает на ошибку там, где собственные тесты агента молчали.

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

Что означает результат Default

Default не проиграл ни одной технике с большим отрывом. На задаче с IMAP и той же GPT-6 Astra Default снова выглядел неплохо, а отдельные условия давали чуть более высокую корректность при более высокой стоимости прогона.

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

Почему вывод «тесты от ИИ доказанно бесполезны» неверен

Вирусное утверждение «тесты от ИИ доказанно бесполезны» не следует из проверки на DeepSWE. Логическая подмена здесь типичная: единичный прогон на конкретной задаче с конкретной моделью превращают в общее правило о тестировании как таковом.

Разница между утверждениями огромная. «В этом прогоне техника не дала прироста» и «техника доказанно бесполезна» различаются так же, как «я не нашёл баг за час» и «багов в коде нет».

Малая выборка и собственное предупреждение автора

Автор прямо предупреждает: данных мало, далеко идущие выводы делать нельзя. Разница в 4,6 процентного пункта между TDD и дифференциальным тестированием на выборке такого размера не закрывает вопрос о том, какая техника лучше, она задаёт направление следующей проверки.

Практическая дисциплина простая: любой процент из чужого прогона стоит читать вместе с размером выборки, задачей и моделью. Если одного из этих параметров нет, перед вами скорее мнение в цифрах, чем измерение.

Почему результат зависит от модели и задачи

На Zstd с GPT-5.6 Sol агенты тратили в среднем $3,50 на уровне усилий medium и $5,50 на xhigh, добиваясь полной корректности примерно в 63% и 77% случаев. С GPT-6 Astra на той же задаче агент тратит $1 на medium и проходит все тесты более чем в 99% случаев: бенчмарк упёрся в потолок, и разницу между техниками тестирования на нём уже не измерить. Сводка по этой линии экспериментов есть в материале с сравнением условий.

Задача тоже задаёт потолок и пол. RFC на IMAP оказался слишком сложным для GPT-5.6 Sol, а с GPT-6 Astra распределение результатов уже получается. Техника тестирования работает в связке «модель плюс задача плюс бюджет», и выдёргивать её из этой связки рискованно.

Похожий эффект виден на публичных замерах: в разборе MultiLangBench и теста OpenAI на переносе COBOL GPT-6 Astra проходит 87,4% тестов против 26,8% у GPT-5.6 Sol, а GPT-6.1 Sol доходит до 97,9%. Разрыв между поколениями моделей здесь в разы больше, чем разрыв между техниками тестирования в эксперименте с Pandoc.

Фаззинг, property-based тесты и ACL2: что удивило

ACL2 и property-based библиотеки вроде Proptest показали себя лучше ожидаемого. Это неожиданная часть результата: формальные и полуформальные подходы обычно считают слишком дорогими для агентской работы, а на практике агент доводил их до чего-то осмысленного.

Property-based тестирование: Proptest и не только

Идея property-based подхода в том, что вместо конкретных примеров формулируются свойства, которые обязаны выполняться для всех входов: конвертация туда и обратно возвращает исходный документ, размер вывода не меньше размера значимого содержимого, повторный запуск даёт идентичный результат.

Агенту проще проверить инвариант на сотнях сгенерированных входов, чем угадать все интересные кейсы вручную. Порог входа здесь свой: свойства нужно сформулировать корректно и так, чтобы они не оказались тавтологией. Плохо сформулированное свойство проходит всегда и не ловит ничего. ACL2 в этом смысле ещё строже, там нужна формальная постановка задачи.

Фаззинг с агентом: почему старая модель буксовала

GPT-5.6 Sol при просьбе заняться фаззингом генерировал массу бесполезных случайных входов. Агенты на GPT-6 Astra в той же просьбе фаззят структурированно: реально задействуют пути в коде и находят нетривиальные баги.

Практический намёк: просить агента о фаззинге имеет смысл, но отдача зависит от модели. На слабой модели это просто сожжённый бюджет. Как фаззеры и LLM-агенты делят работу на реальной цели, разобрано в кейсе Fuzzilli против LLM-агента BigSleep на движке V8: 45 против 37 исправленных уязвимостей за полгода при пересечении около четверти находок.

Практические выводы: как тестировать код AI-агента

  1. Держите внешний набор тестов, скрытый от агента. Это единственный критерий, который нельзя обойти подгонкой. Тесты, написанные тем же агентом, полезны как черновик, но не как доказательство корректности.
  2. Ищите эталон для дифференциального сравнения. Старая версия продукта, референсная библиотека, вывод конкурентного инструмента. Расхождение на реальных входах находит ошибки там, где собственные тесты молчат.
  3. Не считайте TDD панацеей для агента и не отказывайтесь от него догматически. В прогоне на Pandoc TDD оказался последним, но разрыв небольшой, а причина скорее в том, как агент фиксирует неверные ожидания в первых тестах.
  4. Меряйте стоимость инструкций, а не только результат. В эксперименте на IMAP часть условий давала чуть более высокую корректность за более высокие деньги, а Default держался на уровне. Считайте цену прогона вместе с долей успеха.
  5. Property-based подход и фаззинг пробуйте на сильных моделях. Proptest и ACL2 удивили, фаззинг на GPT-6 Astra нашёл нетривиальные баги, на GPT-5.6 Sol те же просьбы дали мусорные входы.

Каждый пункт работает как гипотеза для собственного замера, а не как готовое правило: выборка в 25 прогонов на условие слишком мала для категоричных рекомендаций, и автор говорит об этом прямо.

Мини-чеклист перед тем, как просить агента о тестах

  • Есть ли набор тестов, который агент не видит и не может изменить?
  • Есть ли эталон или предыдущая версия для дифференциального сравнения?
  • Сформулированы ли свойства как инварианты, а не как пересказ текущего поведения кода?
  • Какой бюджет на один прогон и сколько прогонов вы готовы оплатить?
  • Какая модель используется и упирается ли задача в её потолок (как Zstd с GPT-6 Astra на уровне medium)?
  • Кто и как проверяет результат, кроме самого агента?

Чего этот эксперимент не доказывает

Ограничения стоит держать в голове целиком. Задача одна (Pandoc), модель одна (GPT-6 Astra), по 25 прогонов на условие, цены розничные. Результаты на Zstd и IMAP показывают другую картину: где-то бенчмарк упёрся в потолок, где-то сменилась сложность задачи.

Скрытые тесты агентам не показывают, поэтому целенаправленно улучшать результат под них агент не может, и это плюс методики. Но и переносить проценты с Pandoc на свой проект с другой кодовой базой и другими требованиями нельзя.

Практический шаг на сегодня: возьмите одну свою типовую задачу для агента, соберите десяток реальных входов и запустите два условия, дифференциальное сравнение с эталоном и работу без инструкций по тестам. Два прогона на условие дешевле $90 тысяч, зато дадут ответ про ваш код и вашу модель, а не про Pandoc.

Подписаться на канал