3,583 papers
arXiv:2610.16870 84 12 окт. 2026 г. FREE

Проверки «по спецификации, а не по коду»: почему агенты пишут тесты под готовую реализацию и как это ловить

КЛЮЧЕВАЯ СУТЬ
Обнаружено: кодовые агенты (Codex, Claude Code, OpenCode) пишут тесты по коду, который лежит перед глазами, а не по ТЗ. Метод позволяет получать тесты, которые ловят баги и не бракуют рабочую переделку кода. Фишка: не давай коду роль образца, назови стандартом ТЗ и заставь агента вычёркивать всё, о чём ТЗ молчит. Иначе в тестах появляются ложные тревоги: требуют порядок элементов или текст ошибки, которых в ТЗ нет. Лучший агент в исследовании строит верные проверки только на 63% задач.
Адаптировать под запрос
⚡

TL;DR

Исследование показывает, как кодовые агенты (Codex, Claude Code, OpenCode) пишут проверки по текстовому ТЗ. Агенту дают ТЗ, репозиторий и готовую реализацию. Он должен написать набор проверок: генератор тестовых сценариев (с какими аргументами вызывать код) и сами проверки (что должно выполняться). Проверку тестируют на трёх реализациях: эталонной, с внедрённым нарушением и валидной альтернативной. Альтернативная написана иначе, но ТЗ не нарушает.

Главная находка: агенты пишут проверки, которые копируют поведение реализации, а не требования ТЗ. Поэтому проверка ловит баги, но заодно бракует рабочий код: требует конкретный порядок элементов, точный текст ошибки или побочный эффект, о которых ТЗ молчит. Лучший результат — ровно верные проверки лишь примерно на 63% задач. Нарушение агенты находят чаще, чем пишут верные проверки: разрыв 11–22 пункта съедают ложные тревоги. Если показать агенту реализацию с багом, он теряет 19–31 пункт верности: его проверки либо принимают баг, либо бракуют правильный код. Агент «заземляет» проверки на код перед глазами.

Метод оценки из статьи переносится в практику простой схемой: проверь тесты агента не только на «ловит баг», но и на «пропускает корректную переделку». Решающий критерий качества проверок — «не больше и не меньше, чем требует ТЗ». Следствие для работы: по возможности не давай агенту код, когда он пишет проверки по ТЗ. Если код всё же в контексте, прямо требуй считать стандартом ТЗ, а не код.

📌

Схема проверки тестов агента (так оценивают в статье)

ШАГ 1: ТЗ → разбить на атомарные требования (одно требование = одно нарушение)
ШАГ 2: Агент получает ТЗ + репозиторий + реализацию → пишет набор проверок:
        а) генератор сценариев (какие аргументы подавать)
        б) проверки (что должно выполняться), не привязанные к конкретному сценарию
ШАГ 3: Прогон на трёх реализациях:
        • эталонная        → проверки ДОЛЖНЫ принять
        • валидная альтернатива (другой код, ТЗ не нарушает) → ДОЛЖНЫ принять
        • с нарушением ТЗ  → ДОЛЖНЫ отклонить
ШАГ 4: Верно = нарушение отклонено И всё корректное принято
        Ложная тревога = отклонён корректный код
🚀

Пример применения

Задача: Интернет-магазин на Python, как у Ozon или Wildberries. Есть функция расчёта цены корзины с промокодом. ТЗ: «Скидка по промокоду не может превышать 30% от суммы корзины. Скидка не применяется к товарам с пометкой "уценка". Итог округляется вниз до целого рубля». Код уже написан. Нужно, чтобы агент написал проверки, которые поймают будущие баги при рефакторинге, но не сломаются от безобидных изменений вроде другого порядка позиций в чеке.

Промпт:

Ты пишешь проверки для функции apply_promo в файле cart/pricing.py.

Стандарт правильности — ТЗ ниже, а не текущий код. Код может не соответствовать ТЗ.

ТЗ:
1. Скидка по промокоду не превышает 30% от суммы корзины.
2. Скидка не применяется к товарам с пометкой "уценка".
3. Итоговая сумма округляется вниз до целого рубля.

Сделай для КАЖДОГО пункта ТЗ отдельно:
А) Генератор сценариев: список разных вызовов (пустая корзина, одна позиция,
   только уценка, промокод на 50%, копейки в сумме, смесь обычных и уценённых).
   Для каждого — конкретные аргументы.
Б) Проверки: утверждения о результате, которые следуют ТОЛЬКО из текста ТЗ.
   Проверка не привязана к конкретному сценарию и годится для любого вызова.

Правила проверок:
- Проверяй не больше и не меньше, чем требует ТЗ.
- Не проверяй то, о чём ТЗ молчит: порядок позиций в ответе, текст сообщений,
  названия внутренних полей, число вызовов вспомогательных функций.
- Если сомневаешься, следует ли утверждение из ТЗ, выкинь его и запиши в список
  «Не проверяю, потому что ТЗ молчит».

В конце для каждой проверки ответь: «Какой корректный код она могла бы
ошибочно отклонить?» Если такой код легко представить, ослабь проверку.

Результат: Агент выдаст для каждого пункта ТЗ набор сценариев и проверок, не привязанных к конкретному вызову. Отдельным списком он перечислит, что сознательно не проверяет. В конце будет самокритика по каждой проверке: какой корректный вариант кода она могла бы забраковать. Вероятнее всего, в проверках не будет жёсткой привязки к порядку позиций или тексту ошибок. Но полной гарантии это не даёт: даже лучшие агенты в исследовании промахивались на трети задач. Поэтому проверки всё равно надо прогнать на заведомо правильной переделке кода и на заведомо сломанной.

🧠

Почему это работает

Слабость. Если в контексте лежит готовый код, модель берёт его как образец. Тест из таких проверок превращается в «пересказ того, что код делает сегодня». Любое отличие от кода, даже допустимое по ТЗ, он видит ошибкой. Если в коде баг, проверка зафиксирует и баг. Это показал эксперимент: подсунули реализацию с нарушением, и все агенты потеряли 19–31 пункт верности.

Сильная сторона. Модель умеет читать текстовые требования и выводить из них утверждения о результате. Ещё она хорошо придумывает разнообразные входные данные. Находить нарушения, когда есть что проверять, ей удаётся: обнаружение у агентов заметно выше верности. Слабое место в проверках, а не в количестве сценариев.

Что делает подход. Он разводит источники: стандарт — ТЗ, код — только справка. Он заставляет отдельно отвечать на вопрос «что из этого ТЗ реально требует?» и вычёркивать лишнее. Явный список «не проверяю, потому что ТЗ молчит» работает как барьер от привычки перечислять всё, что видно в коде.

Рычаги управления: - Убрать реализацию из контекста совсем → самый сильный рычаг против копирования кода (но тогда агент не сможет запускать сценарии). - Строгость вычёркивания («при сомнении выкинь») → ослабь, если пропускаются баги; усиль, если агент бракует корректный код. - Разбивка ТЗ на атомарные пункты → одно требование на одну проверку, проще понять, что именно сломалось. - Финальный вопрос «какой корректный код ты бракуешь» → можно задать отдельным проходом другой модели.

📋

Шаблон промпта

Ты пишешь проверки для {функция_или_модуль} в {файл}.

Стандарт правильности — ТЗ ниже, а не текущий код.
Код может не соответствовать ТЗ, не копируй его поведение.

ТЗ:
{нумерованный_список_требований}

Сделай для КАЖДОГО требования отдельно:
А) Генератор сценариев: набор конкретных вызовов (аргументы), включая
   граничные случаи: {какие_граничные_случаи}.
Б) Проверки: утверждения о результате, которые следуют ТОЛЬКО из текста ТЗ.
   Проверка не привязана к конкретному сценарию и работает для любого вызова.

Правила:
- Проверяй не больше и не меньше, чем требует ТЗ.
- Не проверяй то, о чём ТЗ молчит: {что_ТЗ_не_фиксирует}.
- Сомневаешься — выкинь утверждение и запиши в «Не проверяю, потому что ТЗ молчит».

В конце по каждой проверке ответь: какой корректный код она могла бы ошибочно
отклонить? Если легко представить — ослабь проверку.

Что подставлять: - {нумерованный_список_требований} — ТЗ, разбитое на отдельные пункты. Одно требование должно ломаться независимо от других. - {какие_граничные_случаи} — пустые данные, лимиты, копейки, нестандартные типы. - {что_ТЗ_не_фиксирует} — порядок элементов, тексты ошибок, внутренние поля, побочные эффекты. Эти пункты ты знаешь лучше агента.

🚀 Быстрый старт — вставь в чат:

Вот шаблон промпта для проверок «по ТЗ, а не по коду». Адаптируй под мою задачу: {опиши_функцию_и_ТЗ}.
Задавай вопросы, чтобы заполнить поля.

[вставить шаблон выше]

LLM спросит, какие требования в ТЗ, какие граничные случаи важны и что в ТЗ сознательно не зафиксировано. Это нужно, чтобы метод работал: без чёткого списка того, о чём ТЗ молчит, агент не сможет отсечь лишние проверки.

⚠️

Ограничения

⚠️ Статья — бенчмарк, а не готовый метод. Авторы измерили, где агенты ошибаются, но не проверили, насколько помогает промпт вроде шаблона выше. Шаблон собран из формулировки задачи в статье и главных находок. Прирост от него в статье не измерен.

⚠️ Лучший результат всё равно слабый. Ни один агент не построил верный набор проверок больше чем на 63% задач. Прогони проверки на правильной и сломанной версиях кода сам.

⚠️ Нужна чёткая спецификация. Задачи в бенчмарке — «атомарные» требования, выписанные из хорошего ТЗ. Если ТЗ расплывчато («работает быстро», «удобно»), метод не сработает: нечего вычёркивать и не с чем сверять.

⚠️ Только Python и синтетические нарушения. Баги внедряла другая модель, не реальная команда разработчиков. Проверено на Python-репозиториях с открытым кодом.

⚠️ Отказ от кода в контексте имеет цену. Если убрать реализацию, агент не сможет запускать сценарии. Баланс — оставить код, но жёстко приказать считать стандартом ТЗ.

🔍

Как исследовали

Исследователи взяли 30 реальных функций из открытых Python-проектов (13 репозиториев) и разбили каждое ТЗ на мелкие требования. Получилось 291 задача. Для каждой требование нарушали: модель Claude Opus 5 вносила в код баг, который не ловили оригинальные тесты. Вторая модель из другого семейства, GPT-5.6-sol, голосованием из трёх ответов подтверждала, что это настоящее нарушение, а не безобидное отличие. Неудачные варианты выбрасывали. «Валидными альтернативами» становились баги из соседних требований: для текущего ТЗ они корректны, а для своего — нет. Двое авторов вручную проверили 50 задач и согласились между собой в 94,7% случаев; с решением пайплайна совпали на 98%.

Затем четыре агента (Codex с GPT-5.6-sol, Claude Code с Opus 5, OpenCode с DeepSeek-V4-Pro и GLM-5.3) по 80 вызовов модели на задачу писали наборы проверок. Верными проверки считались, если баг отклонён, а всё корректное принято. Верность получилась 45–63%, обнаружение 65–82%, ложные тревоги 15–27%. Удивила разница в рейтингах: GPT-5.6-sol обнаружил нарушения на 8 пунктов чаще GLM-5.3, но и ложных тревог дал на 8 пунктов больше, и верность у них оказалась почти равной. Ложные тревоги составили 42–60% всех неудач.

Чтобы понять, виноваты сценарии или проверки, исследователи подставили агентам «идеальные» сценарии, заведомо вскрывающие баг. У трёх из четырёх агентов большинство пропущенных нарушений осталось: проверки по-прежнему принимали баг. Значит, узкое место в самих проверках. Дополнительно агентам показывали реализацию с багом вместо эталонной. Все четверо потеряли 19–31 пункт верности и стали бракуя неизвестную им эталонную реализацию в 12–41% задач: агент подгонял проверки под то, что видел.

💡

Адаптации и экстраполяции

🔧 Техника: добавить «альтернативную реализацию» → ловим ложные тревоги

После того как агент написал проверки, попроси его (или другого агента) переписать функцию иначе: другой порядок, другие внутренние структуры, другие тексты ошибок, но с тем же поведением по ТЗ. Прогони проверки на ней. Если что-то упало, это ложная тревога: проверка требует больше, чем сказано в ТЗ. Идея взята из дизайна бенчмарка, но в статье эту процедуру применяют для оценки, а не как приём для практика.

🔧 Техника: сломать код специально → ловим пропущенные баги

Попроси другого агента: «Внеси в код ровно одно нарушение пункта {N} ТЗ, которое не видно по чтению кода, но видно при запуске». Если проверки пропускают нарушение, они слабы.

Экстраполяция: два прохода с разделением ролей.

Проход 1 (агент А, БЕЗ доступа к коду):
Вот ТЗ: {ТЗ}. Напиши проверки только из текста ТЗ. Код тебе не показан.

Проход 2 (агент Б, С доступом к коду):
Вот ТЗ, вот код и вот проверки агента А. Запусти проверки на коде.
Если проверка падает на корректном коде, определи по ТЗ: ошибка в коде
или проверка требует больше, чем в ТЗ? Не меняй проверку, если ТЗ её подтверждает.

Это моя комбинация, не из статьи: она применяет вывод «агент копирует код» через разделение контекста.

🔗

Ресурсы

  • SpecGuardBench: Can Coding Agents Construct Reliable Validation Harnesses from Natural Language Specifications? (Preprint)
  • Код и данные: github.com/coxhin/SpecGuardBench, huggingface.co/datasets/coxhin/SpecGuardBench
  • Авторы: Zhiqing Zhong, Mingyu Chen, Aoyang Fang, Yuzhong Zhang, Haoye Tian, Lionel Briand, Boxi Yu, Pinjia He
  • Организации: The Chinese University of Hong Kong, Shenzhen; Aalto University; Lero (Research Ireland Centre for Software); University of Limerick; University of Ottawa
  • Основа датасета: FeatureBench (Zhou et al., 2026)

📋 Дайджест исследования

Ключевая суть

Обнаружено: кодовые агенты (Codex, Claude Code, OpenCode) пишут тесты по коду, который лежит перед глазами, а не по ТЗ. Метод позволяет получать тесты, которые ловят баги и не бракуют рабочую переделку кода. Фишка: не давай коду роль образца, назови стандартом ТЗ и заставь агента вычёркивать всё, о чём ТЗ молчит. Иначе в тестах появляются ложные тревоги: требуют порядок элементов или текст ошибки, которых в ТЗ нет. Лучший агент в исследовании строит верные проверки только на 63% задач.

Принцип работы

Хороший тест принимает любую реализацию, которая не нарушает ТЗ. Поэтому в статье каждую проверку гоняют на трёх версиях кода. Эталонная и валидная альтернатива (написана иначе, но ТЗ не нарушает): обе должны пройти. Версия с нарушением должна упасть. Тест хорош, когда проверяет не больше и не меньше, чем требует ТЗ. Это как приёмка квартиры по договору. Ты сверяешь с договором, а не с тем, что построили. Если в договоре нет слов про цвет дверей, коричневая дверь не повод отказываться от приёмки. Агент же часто пишет: «двери должны быть коричневые, ведь такие стоят сейчас».

Почему работает

Модель берёт готовый код как образец. Тест превращается в пересказ того, что код делает сегодня. Любое отличие от кода он видит ошибкой, даже допустимое по ТЗ. Если в коде баг, тест закрепит и баг. Проверили в эксперименте: агентам показали реализацию с нарушением, и верность проверок упала на 19–31 пункт. Агент не хуже читает ТЗ, чем код, но выбирает то, что виднее: код перед глазами. Отсюда и разрыв: нарушения агенты находят чаще, чем строят верные проверки, на 11–22 пункта. Разницу съедают ложные тревоги. Слабое место не в количестве сценариев, а в самих утверждениях. Поэтому промпт делает три вещи. Он называет ТЗ стандартом. Он требует список «не проверяю, потому что ТЗ молчит». Он просит в конце найти корректный код, который тест мог бы забраковать.

Когда применять

Рефакторинг и регрессионные тесты → когда агент пишет проверки для функции с чётким ТЗ из отдельных пунктов, особенно если после переписывания кода тесты падают на безобидных изменениях (порядок позиций, текст сообщений). НЕ подходит для расплывчатого ТЗ вроде «работает быстро» и «удобно»: нечего вычёркивать и не с чем сверять. Важно: статья даёт бенчмарк, а не готовый метод. Промпт собран из её находок. Прирост от него авторы не измеряли. Проверено только на Python.

Мини-рецепт

1. Нарежь ТЗ на пункты: одно требование — одно нарушение. Пронумеруй.
2. Назови стандарт: «Стандарт правильности — ТЗ, а не текущий код. Код может быть с багом».
3. Попроси сценарии и проверки отдельно: сначала список вызовов с граничными случаями, потом утверждения, которые верны для любого вызова.
4. Запрети лишнее: перечисли, что ТЗ не фиксирует. Например, порядок элементов, тексты ошибок, внутренние поля.
5. Дай право выбросить: «Сомневаешься — вычеркни и запиши в список «Не проверяю, потому что ТЗ молчит»».
6. Запроси самокритику: для каждой проверки «какой корректный код она могла бы ошибочно отклонить?». Для надёжности пусть это сделает другая модель.
7. Прогони вживую: возьми заведомо правильную переделку и заведомо сломанную. Первая должна пройти, вторая упасть. Если можно, вообще не показывай агенту код, но тогда он не запустит сценарии.

Примеры

[ПЛОХО] : Напиши тесты для функции apply_promo в cart/pricing.py
[ХОРОШО] : Ты пишешь проверки для apply_promo в cart/pricing.py. Стандарт правильности — ТЗ ниже, а не текущий код. Код может не соответствовать ТЗ. ТЗ: 1) скидка по промокоду не больше 30% от суммы корзины; 2) скидка не применяется к товарам с пометкой «уценка»; 3) итог округляется вниз до целого рубля. Для каждого пункта отдельно: А) список вызовов (пустая корзина, только уценка, промокод на 50%, копейки в сумме); Б) утверждения, которые следуют только из текста ТЗ. Не проверяй порядок позиций, тексты сообщений и внутренние поля. Сомневаешься — выкинь и запиши в «Не проверяю, потому что ТЗ молчит». В конце по каждой проверке ответь: какой корректный код она могла бы ошибочно отклонить? Разница в том, что в плохом случае агент перепишет поведение кода в тесты. Он зафиксирует порядок позиций в чеке и точный текст ошибки. Любая нормальная переделка кода сломает такие тесты. В хорошем случае тесты проверяют только три правила ТЗ, а лишнее агент вынес в отдельный список.
Источник: SpecGuardBench: Can Coding Agents Construct Reliable Validation Harnesses from Natural Language Specifications?
ArXiv ID: 2610.16870 | Сгенерировано: 2026-10-15 00:10

Проблемы LLM

ПроблемаСутьКак обойти
Модель с готовым образцом в контексте проверяет по образцу, а не по требованиямДаёшь ТЗ и готовый код. Просишь написать проверки по ТЗ. Модель берёт код как образец. Проверки фиксируют всё, что код делает сегодня: порядок элементов, текст ошибок, побочные эффекты. ТЗ об этом молчит. Корректная переделка кода их не проходит. Если в коде баг, проверка его принимает как норму. То же бывает при ревью, при оценке ответов с эталоном, при составлении критериев приёмки. Образец перед глазами перетягивает внимание на себяЕсли запускать код не нужно, убери его из контекста. Это самый сильный рычаг. Если код нужен, пиши: «Стандарт правильности — ТЗ. Код может ему противоречить. Не копируй его поведение». Дай список того, что ТЗ не фиксирует: порядок, тексты ошибок, внутренние поля. Эффект самой инструкции не измерен, поэтому проверяй результат методом ниже

Методы

МетодСуть
Проверка проверок на трёх версиях кода — ловит и пропуски, и ложные тревогиПроверь не только «ловит баг». Прогони набор проверок на трёх версиях. 1. Эталон — должен пройти. 2. Корректная переделка — другой код, ТЗ не нарушает, должен пройти. 3. Версия с внедрённым нарушением — должна быть отклонена. Набор верен, только если нарушение отклонено И всё корректное принято. Почему работает: тест, который бракует всё подряд, «ловит» любой баг. Одна проверка на баг этого не покажет. Вторая версия выявляет лишнюю строгость. Переделку и нарушение можно попросить написать у другой модели. Когда да: проверки пишет модель, а код потом будут менять. Так же можно проверять критерии для оценки ответов моделью. Когда нет: ТЗ расплывчатое («быстро», «удобно»). Нечего считать нарушением и нечем сверять
Список «не проверяю, потому что ТЗ молчит» и вопрос про ложный отказ — режет лишние проверкиРазбей ТЗ на нумерованные пункты. Для каждого пункта проси проверки, которые следуют только из текста. Добавь правило: «Сомневаешься — выкинь и запиши в список „не проверяю, потому что ТЗ молчит“». В конце спроси по каждой проверке: «Какой корректный код она могла бы ошибочно отклонить? Если легко представить — ослабь». Почему работает: модель по привычке перечисляет всё, что видит. Явный список исключений ломает эту привычку. Вопрос про корректный код заставляет искать ложные отказы, а не только баги. Если пропускаются баги, смягчи правило «при сомнении выкинь». Если бракуется корректный код, усиль его. Вопрос можно задать отдельным проходом другой модели. Оговорка: прирост от этого приёма не измерен. Проверяй результат методом выше. Не работает: без чёткого списка того, что ТЗ не фиксирует. Его лучше писать самому
📖 Простыми словами

SpecGuardBench: Can CodingAgentsConstruct Reliable Validation Harnesses from NaturalLanguageSpecifications?

arXiv: 2610.16870

AI-агенты пишут тесты совсем не так, как думают наивные тимлиды. Если скормить модели текстовое ТЗ и готовый репозиторий, она забьёт на требования и пойдёт по пути наименьшего сопротивления. Нейросеть создаёт тупой слепок текущего поведения кода. Вместо проверки бизнес-логики получается зеркало реализации: если в исходнике сидит критический баг, агент заботливо напишет проверку, требующую, чтобы этот баг работал вечно.

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

Бенчмарк SpecGuardBench наглядно показал эту лажу на моделях уровня Codex и Claude Code. Агентам поручили написать сценарии и проверки, а затем прогнали их тесты через эталонный код, версию с ошибкой и валидную альтернативу. Результат — закономерный провал: на коде с дефектом агенты потеряли от 19 до 31 пункта верности. Модели моментально поверили кривой реализации и намертво зафиксировали ошибку в тестах.

Тестировали на логике корзины интернет-магазина, но принцип универсален. Грабли ждут везде: от микросервисов до финтеха, где пытаются прикрутить AI для автогенерации регрессионных тестов. Сгенерированные проверки сломаются при первом же нормальном рефакторинге — скажем, если ты просто поменяешь порядок полей в ответе, хотя ТЗ не нарушено. Мнимая надёжность оборачивается геморроем при первой же правке.

Главный вывод: никогда не давай кодовому агенту готовую реализацию, если хочешь получить честные тестовые сценарии. Заставляй модель писать тесты вслепую, исключительно по тексту ТЗ. Иначе нейросеть просто зацементирует технический долг в твоём репозитории. Хочешь устойчивый пайплайн — изолируй требования от кода, пока AI не нагородил бесполезных костылей.

Работа с исследованием

Адаптируйте исследование под ваши задачи или создайте готовый промпт на основе техник из исследования.

0 / 2000
~0.5-2 N-токенов ~10-30с
~0.3-1 N-токенов ~5-15с