Amiga
Оглавление курса · урок 5 из 13

Модуль 2 · Автоматизация · урок 5 из 13

E2E на Playwright с Codex

E2E-тесты — место, где агент экономит больше всего часов и где он же чаще всего хитрит. Написать спек на Playwright Codex может за минуту, а вот сделать его устойчивым и честным — задача для вас двоих. Разберём рабочий цикл на примере сайта на OctoberCMS с регресс-набором в tests/e2e.

Контекст, без которого будет плохо

Перед первой задачей убедитесь, что агенту доступно:

  • playwright.config.ts — baseURL, проекты (например, десктоп и мобильный Chromium), ретраи, трейсы. Агент должен понимать, что каждый тест прогонится и в мобильном проекте.
  • Существующие спеки и tests/e2e/support — общие хелперы, проверка «работаем только на localhost», фикстуры. Иначе агент напишет свои с нуля.
  • Правила в AGENTS.md — локаторы, запреты, критерий «готово» (см. урок «Настройка Codex под тестирование»).

И отдельно — шаблоны страниц. В OctoberCMS разметка лежит в .htm-файлах темы и partials. Если агент видит шаблон, он находит реальные подписи кнопок и полей, а не угадывает button.submit-btn.

Цикл: кейс → спек → прогон → разбор

Начинайте с проверки, сформулированной словами, — например, из тест-дизайна:

text
Напиши e2e-тест в tests/e2e/feedback-form.spec.ts по кейсам TC-01…TC-04
(ниже). Перед написанием открой шаблон формы в теме и найди реальные
подписи полей и кнопки. Используй хелперы из tests/e2e/support.
Прогони: npx playwright test tests/e2e/feedback-form.spec.ts
Если тест падает — сначала объясни причину, потом правь.
Нельзя: waitForTimeout, force: true, ослабление утверждений.

Фраза «сначала объясни причину» дисциплинирует. Без неё агент склонен менять тест, пока тот не позеленеет, не понимая, почему он падал.

Результат, к которому стоит стремиться:

typescript · tests/e2e/feedback-form.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Форма обратной связи', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/contacts');
  });

  test('не отправляется без имени и показывает ошибку у поля', async ({ page }) => {
    const form = page.getByRole('form', { name: 'Обратная связь' });
    await form.getByLabel('Email').fill('qa@example.test');
    await form.getByRole('button', { name: 'Отправить' }).click();

    await expect(form.getByText('Укажите имя')).toBeVisible();
    await expect(page.getByText('Спасибо, заявка отправлена')).toBeHidden();
  });

  test('принимает телефон вместо email', async ({ page }) => {
    const form = page.getByRole('form', { name: 'Обратная связь' });
    await form.getByLabel('Имя').fill('Тест');
    await form.getByLabel('Телефон').fill('+7 999 123-45-67');

    await expect(form.getByRole('button', { name: 'Отправить' })).toBeEnabled();
  });
});

Обратите внимание: утверждения веб-ориентированные (web-first assertions, await expect(locator)…) — Playwright сам ждёт нужного состояния, и ручные паузы не нужны. Во втором тесте нет отправки формы: тесты, которые реально создают заявку, в таком проекте разрешены только на локальном стенде, и агент должен использовать для них общий хелпер, а не отправлять что попало.

Локаторы и роли

Просите локаторы по ролям и подписям: getByRole, getByLabel, getByText. Это заодно проверка доступности: если у поля нет подписи, getByLabel его не найдёт — и это баг вёрстки, а не повод для CSS-селектора. Попросите агента в таких случаях не обходить проблему, а записать её отдельно.

Если локатор находит несколько элементов, Playwright падает с нарушением строгого режима (strict mode violation). Частая «починка» агента — добавить .first(). Иногда это верно, но чаще означает, что локатор неточен и тест кликает не туда, куда вы думаете. Требуйте сузить область: найти элемент внутри формы или секции.

Как агент «чинит» тесты и почему это опасно

Вот что встречается в диффах регулярно — и что нужно отклонять:

Что сделал агент Чем опасно
await page.waitForTimeout(3000) Медленно и всё равно нестабильно; прячет гонку
click({ force: true }) Кликает по перекрытому элементу — пользователь так не может
Увеличил timeout или retries Маскирует медленную страницу или флак
Заменил toHaveText('…') на toBeVisible() Тест больше не проверяет содержимое
Обернул шаг в try/catch Ошибка проглатывается, тест зелёный всегда
Добавил test.skip Проблема исчезла из отчёта, но не из продукта

Хорошая привычка — после каждой сессии смотреть дифф тестов отдельно от кода: git diff -- tests/. Подробно о проверке — в уроке «Как проверять тесты, написанные агентом».

Разбор падений

Когда тест падает, агенту нужен не только текст ошибки. Playwright складывает в test-results скриншот и вложения упавшего теста, а при настройке trace: 'on-first-retry' — ещё и трейс. Попросите агента прочитать ошибку и вложения и сформулировать гипотезу: «элемент не появился», «появился, но с другим текстом», «перекрыт модальным окном куки». Трейс удобнее смотреть вам самим: npx playwright show-trace <путь к trace.zip>.

Если тест падает только в мобильном проекте, это часто не баг теста, а реальная проблема адаптива: меню свёрнуто в бургер, кнопка ушла за край экрана. Не давайте агенту исключить мобильный проект «для стабильности».

Запись сценариев браузером

Иногда быстрее показать сценарий, чем описать. У Playwright есть npx playwright codegen для записи действий человеком. Агент может пройти сценарий сам через браузер — встроенный или Playwright MCP — и потом написать тест по тому, что увидел. В Playwright MCP есть дополнительные возможности для тестов, например генерация локатора для элемента; они включаются флагом --caps. README Playwright MCP при этом прямо советует кодинг-агентам рассмотреть Playwright CLI с навыками как более экономный по токенам путь (playwright-mcp). Подробнее — в уроке «Браузер в руках агента».

Попробуйте сами

10–15 мин на рабочем месте
  1. Возьмите один ручной кейс и попросите агента написать по нему спек с запретами из урока. Проверьте, что он прогнал тест в обоих проектах из конфига.
  2. Сломайте в шаблоне подпись кнопки, прогоните тест и посмотрите, что агент предложит: исправить тест или сообщить о расхождении.
  3. Выполните git diff -- tests/ после сессии и найдите хотя бы одно место из таблицы «починок», если оно есть.

Коротко

  • Агенту нужны конфиг Playwright, существующие хелперы, правила из AGENTS.md и шаблоны страниц.
  • Локаторы по ролям и подписям; отсутствие подписи — баг вёрстки, а не повод для CSS-селектора.
  • Веб-ориентированные утверждения вместо пауз; force, waitForTimeout, try/catch и skip — отклонять.
  • При падении — сначала причина, потом правка; дифф тестов смотреть отдельно.
  • Падение только в мобильном проекте — частый признак настоящего бага адаптива.
Отметка хранится только в вашем браузере
Хотите связаться с владельцем
компании напрямую?
Дмитрий Тарасов
Дмитрий Тарасов
СЕО

НАПИСАТЬ

Написать в MAX