Умеют ли AI-агенты тестировать? Эксперимент с 26 техниками верификации
Ранее Dan Luu отмечал парадокс: качественные техники тестирования делают агентов эффективнее, но качество софта в целом снижается — значит, дефолтные практики разработчиков не работают. В этом эксперименте он проверил, улучшают ли простые инструкции («используй TDD», «используй Lean 4», «используй property-based testing») корректность кода, который пишут агенты. По сути, это тест на то, как агент работает под руководством человека без экспертизы в тестировании, который просто «что-то слышал» о разных техниках.
Устройство эксперимента
За основу взят эвал Zstd — агенты реализуют формат сжатия Zstd на Rust по спецификации. Условий было 26: от дефолта (без инструкций) через TDD, фаззинг, мутационное и метаморфное тестирование до формальных методов (Verus, Lean 4, Alloy, TLA+, Kani, ACL2, Creusot, SMT-солверы) и дифференциального тестирования. Плюс четыре скилла: официальный скилл Hegel, тестовый скилл ECC (коллекция с 250k звёзд на GitHub), скилл property-based testing от Trail of Bits и небольшой самописный скилл автора.
Каждое условие — в среднем 80 запусков Codex с GPT-5.6 Sol на уровнях effort medium и xhigh. Метрика строгая: доля запусков, прошедших 100% скрытых тестов.
Прогнозы сбылись
Автор заранее зарегистрировал прогнозы, и все они сбылись:
- TDD будет хуже дефолта (уверенность 55%) — сбывается
- Формальные методы не превзойдут дефолт (52%) — сбывается, но не по той причине, что он ожидал: агенты просто не умеют ими пользоваться
- Инструкция «не делай ошибок» не поможет (95%) — сбывается: no-op лучше, чем заставлять агента делать бесполезную работу
- Ни один из трёх популярных тестовых скиллов не превзойдёт отсутствие скилла — сбывается
Главный результат: ничего не работает лучше дефолта
Ни одна техника не превзошла дефолт с заметным отрывом. Default (без инструкций) показал результат выше среднего. На xhigh фаззинг и property-based testing в среднем чуть лучше формальных методов, но картина смешанная. Скиллы, которые порекомендовал сам Codex, дали результат хуже дефолта; маленький самописный скилл выступил неплохо.
Причина видна при взгляде на то, что агенты реально делали: получив название библиотеки или техники, агенты либо писали обычные юнит-тесты внутри чужого фреймворка, либо применяли технику поверхностно, не делая того, что даёт технике ценность. Цитата Gary Bernhardt очень точно описывает поведение:
Подход AI-агентов к тестированию, если коротко: взять патологические случаи, о которых спорили противники моков 15 лет назад, никогда моками не пользуясь. Сделать эти патологии основой тестовой стратегии.
С формальными методами агенты доказывали нерелевантные свойства. С property-based testing — упирали на полностью случайные входы, которые бьют по путям отбора невалидных данных, или проверяли тривиальные свойства на случайных входах с низкой ценностью.
Как это выглядело по условиям
Формальные методы (Verus, Alloy, Lean 4, Spin, Creusot, ACL2). Агенты писали доказательства абстрактных свойств мимо реального кода. В Verus попадались вакуумные доказательства вида A => A: предпосылки «0 < a <= window, 0 < b <= window, 0 < c <= window» и заключение — то же самое в другом порядке. Alloy занял второе место с конца: в одном случае контрпример опирался на 8-битное переполнение, невозможное при 64-битном usize, и просто усложнил код. Корректность везде обеспечивалась обычными Rust-тестами через #[test], а не формальным инструментом.
Дифференциальное тестирование — третье место с конца. Ни один агент из 160 не написал две полные независимые реализации для сравнения. В случаях, где подход мог поймать баг, агенты дважды делали одно и то же и кодировали один и тот же баг в обеих версиях.
TDD. Инструкция заметно изменила поведение: тестов вдвое больше, работа идёт итеративно, в 67 из 160 запусков падающие тесты появлялись до существенной реализации (в дефолте — 0 из 160). Но корректность хуже: TDD-агенты чаще проваливали тест на jump table для четырёх Huffman-потоков, писали тесты с четырьмя идентичными тривиальными потоками и кодировали неверное поведение в тестах. Гипотеза Yossi Kreinin: TDD толкает к чёрному ящику, а для сложной механики белый ящик эффективнее — до написания кода ещё не известно, что будет трудным.
Фаззинг. Агенты сыпали случайными байтами, которые почти всегда уходили в пути отбора невалидного ввода. Но показательно: в 10 запусках из 160, где агенты генерировали структурированные случайные входы, реальные баги находились в половине случаев. Агенты в каком-то смысле умеют тестировать хорошо — просто не делают этого без пинка.
SMT-солверы. Самый яркий пример бессмысленного применения: есть вычисление, которое должно быть byte1 + (byte2 << 8) + 0x7F00, а многие агенты писали byte1 + (byte2 << 8) | 0x7F00. Агенты доказывали свойства этого вычисления солвером — и затем всё равно писали неверный код.
TLA+. 159 из 160 агентов построили модель конечного автомата, но поздно и не там: ни одного случая, где модель привела к изменению Rust-кода. Запуски с более сложным моделированием не показали лучшей корректности.
Скиллы. Скилл Hegel (34k символов плюс 45k Rust-справочник, суммарно более 20k токенов) увеличил стоимость запусков на 26–41% без роста корректности: агенты генерировали ещё больше бесполезных no-panic и round-trip тестов в нетривиальных местах. Скилл Trail of Bits открыли только 108 из 160 запусков, а зависимость proptest не добавлялась, потому что скилл требовал одобрения. ECC выступил почти на уровне дефолта, но анализ по экспозиции показал: чем раньше агент читал скилл, тем хуже результат. Хорошо он выглядел только за счёт запусков, где скилл фактически проигнорировали.
Аудит. 152 из 160 агентов провели аудит после реализации, 151 заявил, что нашёл проблему. Но независимый аудит в свежем контексте делали немногие — чаще аудит повторял те же ошибки, что и реализация. Любопытно, что запуски с отдельным аудирующим субагентом показали результат хуже. На xhigh аудит дал лучшую корректность, на medium — ниже средней, при существенно возросшей стоимости.
Наверху таблицы — Kani (единственный случай за 160 запусков, где реальное применение формального инструмента поймало нетривиальный баг и изменило код), proptest и «случайный» второй proptest-забег (все агенты в условии property-based testing выбрали proptest — shrinking иногда приносил пользу) и самописный скилл автора, который набрал максимум. Но даже он сработал не так, как задуман: агенты почти никогда не делали независимый ре-дерайв в свежем контексте, а правильную идентификацию рискованных зон (например, реверс порядка битстримов между encode и decode) не превращали в тесты, которые её ловят — входы выходили палиндромными, и реверс ничего не менял.
Почему так и что с этим делать
Автор удивлён, что AI-лаборатории не строят RL-окружения для обучения агентам тестировать: агенты отлично научились задачам ограниченной оптимизации рантайма именно потому, что для них легко нагенерить RL-сред. Возможно, дело в том, что знания об эффективных техниках тестирования малораспространены — в подполях, где корректность действительно важна, люди независимо пришли к подходам, противоположным мелким юнит-тестам, и именно на юнит-тестах агентов сейчас и обучают.
Практический вывод из опыта автора и его собеседников: если задать агенту разумную структуру тестирования и триажа, дальше он пополняет её вполне сносно. Jamie Brandon добивался вменяемых e2e-тестов с мокированным IO, только перенеся тесты в отдельный crate и зафиксировав правила в AGENTS.md. Групповое «тестируйся» или название библиотеки не работают; но если посмотреть на результат и дописать пару предложений конкретики — агента обычно удаётся довести до хорошего места. Знание, как тестировать, в модели где-то есть — оно просто не выносится в дефолтное поведение.
Отдельное наблюдение про скиллы: протестированные скиллы написаны как туториалы для человека, объясняющие «как делать», тогда как модели с уже имеющимися знаниями полезнее короткие утверждения, сдвигающие дефолтное поведение. Плюс поведение агентов сильно зависит от harness, модели и уровня effort — то, что работало с GPT-5.5, перестало работать с GPT-5.6, так что портфель скиллов, дифференцированных по модели и effort, — единственное, что имеет смысл для личного использования. Автор даже стал bullish на скиллы для себя: раз фейлмоды предсказуемы, их можно чинить дёшево. А после публикации автор этого поста David R. MacIver (автор Hypothesis и Hegel) публично подтвердил, что скилл Hegel действительно так себе — и уже поставил бенчмарк для его улучшения.
Источник: https://danluu.com/agentic-testing/