Модуль 3 · Баги и регресс · урок 12 из 13
Как проверять тесты, написанные агентом
Этот урок — сердце курса. Агент, который пишет тест и сам же его прогоняет, оказывается в роли и исполнителя, и контролёра. Зелёный прогон в его отчёте означает только то, что тест не упал. Проверит ли тест что-нибудь, если продукт сломается, — отдельный вопрос, и отвечать на него приходится вам.
Почему это отдельная проблема
Биргитта Бёкелер (Thoughtworks) в статье о harness engineering делит контроли вокруг агента на три группы: сопровождаемость кода, соответствие архитектуре и поведение. Проверку поведения она называет «слоном в комнате»: на практике тестам, сгенерированным AI, доверяют слишком много (Harness engineering for coding agent users). Там же она относит мутационное тестирование к проверкам после интеграции.
В Anthropic, описывая долгие автономные задачи, отмечают ещё одну особенность: агент склонен снисходительно оценивать собственную работу, и настроить отдельного скептичного оценщика проще, чем научить генератор самокритике (Harness design for long-running apps). Для QA вывод прямой: проверка должна быть независимой от того, кто писал.
Проверка 1. Тест вообще запускали
Звучит банально, но начинается всё с этого. Требуйте в отчёте агента команду и вывод прогона, а затем запустите тест сами — в чистом терминале, не в сессии агента:
npx playwright test tests/e2e/lead-phone.spec.ts --retries=0--retries=0 важен: если в конфиге для CI стоят ретраи, тест может «пройти» со второй попытки, и вы не заметите нестабильность.
Проверка 2. Тест падает без фикса
Главный вопрос: упадёт ли тест, если исправления нет? Если тест написан к багфиксу, верните код продукта к состоянию до исправления, оставив тест:
# код продукта — как в main, тесты — как в ветке
git restore --source=main -- src/
npx playwright test tests/e2e/lead-phone.spec.ts --retries=0 # должен упасть
git restore -- src/ # вернуть исправлениеСмотрите не только на сам факт падения, но и на сообщение. Тест должен падать из-за бага — «ожидали сообщение об успехе, получили ошибку 500», — а не из-за ненайденного локатора или таймаута. Падение по посторонней причине означает, что тест не проверяет то, что заявлено.
Для новой фичи то же самое делается в обратном порядке: сначала тест, он красный, потом код, тест зелёный. Этот порядок Саймон Уиллисон называет red/green TDD в своих паттернах агентной инженерии (Agentic Engineering Patterns); подробно — в уроке «Тесты как спецификация».
Проверка 3. Утверждения, которые что-то проверяют
Пройдитесь по каждому expect и assert с простым вопросом: какое неправильное поведение продукта сделает это утверждение ложным? Признаки пустых проверок:
| Утверждение | Что не так |
|---|---|
expect(page).toBeTruthy() |
Страница существует всегда |
expect(res.ok()).toBeTruthy() без проверки тела |
Пустой ответ с кодом 200 проходит |
toBeVisible() на контейнере, который есть всегда |
Содержимое не проверяется |
toBeGreaterThan(0) для списка |
Один мусорный элемент проходит |
| Ожидание вычислено тем же кодом, что и результат | Тест согласен с любой ошибкой |
| Снимок (snapshot) обновлён вместе с изменением | Новое поведение принято без проверки |
Утверждение внутри if или try/catch |
Может не выполниться вовсе |
Эту проверку удобно поручить агенту в новой сессии, без контекста написания:
Для каждого теста в tests/e2e/lead-phone.spec.ts:
1. Назови одно конкретное изменение в коде продукта, при котором тест упадёт.
2. Назови одно изменение, которое сломает пользовательский сценарий,
но тест НЕ поймает.
Код и тесты не меняй. Ответ — таблица.Второй пункт — самый полезный: он показывает дыры, о которых автор теста не подумал.
Проверка 4. Мутации
Мутационное тестирование автоматизирует проверку 2: инструмент вносит в код мелкие изменения (мутанты) — меняет > на >=, удаляет вызов, подставляет true, — и смотрит, упадёт ли хоть один тест. Выживший мутант — место, где тесты ничего не проверяют. Для PHP есть Infection, для JavaScript и TypeScript — Stryker. Запускайте их на модуле, а не на всём проекте: это долго.
Для e2e-тестов инструменты мутаций неприменимы, но принцип работает вручную. Попросите агента в отдельном worktree внести три–пять «поломок» в продукт — убрать валидацию поля, поменять текст сообщения об успехе, отключить обработчик кнопки — и для каждой прогнать тесты:
Работай в отдельном worktree. Внеси по очереди 5 изменений в код формы
заявки, каждое из которых ломает поведение для пользователя. После каждого
прогони tests/e2e/lead-*.spec.ts и откати изменение. Отчёт: мутация —
упал ли хоть один тест — какой. Тесты не меняй.Каждая «поломка», которую не поймал ни один тест, — задача на новый тест.
Проверка 5. Что ещё поменял агент
Посмотрите дифф целиком, а не только новые тесты:
git diff --stat main...HEAD
git diff main...HEAD -- tests/Тревожные сигналы: изменения в коде продукта, когда задача была «написать тесты»; правки существующих утверждений; новые skip, ретраи, выросшие таймауты; изменения в playwright.config.ts.
Надёжнее предотвращать это заранее. В Anthropic в одном из экспериментов с долгими задачами агенту разрешали менять в списке проверок только поле «пройдено», а удалять и править тесты запрещали (Effective harnesses for long-running agents). Аналог для нас — правило в AGENTS.md: пишешь тесты — не трогаешь продукт, чинишь продукт — не трогаешь тесты. Жёстче — закрепить это хуком, который отклоняет запись в запрещённые каталоги (см. урок «Хуки»).
Проверка 6. Независимое ревью
Агент не должен быть единственным, кто одобрил собственные тесты. Минимум — ревью в отдельной сессии через /review или неинтерактивно. У codex review цель задаётся одним способом: либо --base, --uncommitted, --commit, либо собственные инструкции текстом — сочетать их нельзя (CLI reference). Для проверки тестов удобны инструкции:
codex review "Сравни ветку с main и проверь только тесты: падают ли они без изменений в src, нет ли пустых утверждений, пауз, skip и ослабленных проверок"Финальное решение о том, что тесты достаточны, остаётся за человеком. Шире о проверке поведения как об открытом вопросе — в уроке «Проверка поведения».
Попробуйте сами
10–15 мин на рабочем месте- Возьмите последний тест, написанный агентом к багфиксу, и выполните проверку 2 командами из урока. Падает ли он и по какой причине?
- Задайте агенту в новой сессии вопрос из проверки 3 про изменение, которое тест не поймает.
- Запустите Infection или Stryker на одном небольшом модуле и посмотрите на выживших мутантов.
Коротко
- Зелёный прогон в отчёте агента ничего не доказывает; прогоните тест сами с
--retries=0. - Тест должен падать без фикса — и по правильной причине.
- Каждое утверждение должно становиться ложным при конкретной поломке продукта.
- Мутации — автоматически для юнит-тестов, вручную в отдельном worktree для e2e.
- Проверяйте весь дифф и разводите права: тесты и продукт не меняются в одной задаче без явной причины.
- Ревью — независимое, в отдельной сессии; решение о достаточности тестов принимает человек.