Сгенерированное приложение может выглядеть убедительно и при этом терять данные, отправлять форму дважды или открывать чужую запись. Проверка должна отвечать на конкретное обещание интерфейса: что пользователь вводит, что система делает и какой результат он видит при успехе и отказе.
Начни с таблицы риска
Возьми одну функцию — например, форму создания заметки — и выпиши сценарии:
| Сценарий | Что пользователь видит | Что проверить в данных |
|---|---|---|
| Пустой заголовок | Объяснение ошибки у поля | Запись не создана |
| Допустимая форма | Состояние загрузки, затем новая заметка | Создана ровно одна запись |
| Сервер недоступен | Сохранился ввод и показан путь повтора | Нет ложного состояния success |
| Двойной клик | Кнопка не обещает два результата | Не появились дубликаты |
| Другой пользователь | Доступ запрещён или запись скрыта | Нет чтения/изменения чужих данных |
Такая таблица лучше общего «потыкать сайт», потому что связывает экран и серверное состояние. Для операций с оплатой, доступом и удалением ставь более строгие проверки и используй тестовую среду, а не настоящие пользовательские данные.
Раздели уровни теста
Unit-тест проверяет отдельную функцию или преобразование; он быстрый, но не подтверждает, что API подключено. Интеграционный тест проверяет границу между слоями, например маршрут и тестовую базу; он может пропустить поведение реального браузера. End-to-end тест проходит сценарий глазами пользователя, но зависит от состояния окружения и не доказывает работу платёжного провайдера в production.
Выбери минимум один тест на бизнес-правило и один путь через браузер для центрального действия. Зафиксируй изолированные данные и способ очистки, чтобы повторный запуск не ломал следующий. Ошибки внешнего API моделируй явно: таймаут, некорректный ответ, лимит и повтор.
Регрессия после каждого изменения
Когда ИИ меняет компонент, попроси его перечислить затронутые сценарии, но проверяй список самостоятельно по diff. Запусти форматирование, статический анализ и тесты, которые реально есть в проекте. После изменения схемы проверь миграцию на пустой и уже заполненной базе. Для авторизации проверь гостя, владельца и пользователя без прав.
Успешное завершение тестовой команды подтверждает только этот запуск и эти тесты. Оно не доказывает нагрузочную безопасность, доступность сервиса, корректность всех ролей или успешную реальную доставку. Сохраняй конкретный лог ошибки и шаги воспроизведения; передавай агенту не весь секретный конфиг, а минимальный безопасный контекст.
Преобразуй найденный баг в защиту
Когда баг устранён, зафиксируй вход, который его воспроизводил, и добавь сценарий на тот уровень, где проявлялась причина. Если ошибку давала чистая функция валидации — unit-тест. Если нарушалась политика владельца записи — интеграционная проверка с двумя тестовыми пользователями. Если интерфейс показывал success раньше ответа — браузерный тест с контролируемым задержанным API. Запиши исходное и новое ожидаемое поведение, чтобы тест не просто закрепил случайную реализацию.
Не полагайся на snapshot всего экрана как единственное доказательство. Он может зафиксировать неверное состояние и усложнить диагностику. Assertions должны описывать обещание: кнопка отключена во время отправки, сообщение об ошибке привязано к полю, строка появляется после подтверждённого сохранения. Для времени, случайности и сетевых отказов задай управляемые значения, иначе результаты будут нестабильны.
До релиза повтори критические сценарии на версии окружения, близкой к production, но с тестовыми данными. Проверь миграцию и переменные среды отдельно. Если внешняя интеграция использует provider sandbox, её успешный тест не подтверждает real-mode account configuration; укажи, что именно было покрыто. Не превращай зелёный индикатор CI в общий вывод «приложение безопасно».
У Playwright есть веб-ориентированные повторяющие проверки, которые ждут ожидаемого состояния страницы; это снижает хрупкость проверки асинхронного UI. Но тест должен проверять значимый результат, а не просто наличие элемента. Успешная кнопка «Отправить» не равна записи в базе: включи в проверку ответ API или подтверждённое состояние тестового хранилища.
Источники: Playwright — assertions, Playwright — лучшие практики.
Сделай проверку частью задачи агенту
Хорошее описание работы для ИИ содержит не только «что построить», но и «как поймём, что работает». Для формы: валидное значение создаёт одну запись; пустое поле получает сообщение; серверный отказ не очищает ввод; чужой пользователь не видит созданную запись. Попроси назвать тесты до изменения. После кода сопоставь этот список с реальным покрытием.
Не проси покрытие 100% без контекста: процент может вырасти тестами вспомогательных функций, пропуская рискованный маршрут. Приоритизируй тесты по последствиям, вероятности отказа и возможности быстро обнаружить дефект. Для продактов с изменяемой схемой удели внимание миграциям; для генеративного ответа — неоднозначным результатам и отказам модели; для форм — повтору и валидации на обеих границах.
Собери после каждого изменения короткий evidence log: commit hash, команда, код выхода, количество тестов, пропуски и ограничения среды. Он помогает понять, что проверено между двумя правками. Не прикладывай в отчёт токены или необезличенные тестовые данные. Этот журнал описывает конкретное выполнение и не превращает один прогон в общую гарантию качества.
