Codegen выдаёт рабочий .spec.ts за время одного прохода по флоу, но сгенерированный тест называется 'test', содержит введённые учётные данные и редко включает больше одного ассёрта. Принимать это за готовый код: самая частая ошибка. Гайд объясняет как запустить codegen, как выбрать лучшие локаторы из предложенных Inspector'ом, как привести вывод в порядок перед коммитом, и где codegen не помогает, чтобы знать что писать вручную.
Что codegen на самом деле генерирует
Codegen: встроенный рекордер тестов Playwright. Запускаешь одной командой, взаимодействуешь со страницей в открывшемся браузере, и боковая панель пишет соответствующий TypeScript (или JavaScript, Python, Java, C#) в реальном времени.
На выходе получается .spec.ts файл который содержит:
- Вызовы
page.goto()для каждой навигации - Методы действий
click(),fill(),check(),selectOption()для каждого взаимодействия - Локаторы для каждого затронутого элемента, выбранные автоматически стратегией локаторов Playwright
- Базовый ассёрт в конце если использовал инструмент ассёртов в Inspector
Сгенерированный код запускается сразу. Вставь в тестовый файл и запусти npx playwright test: в большинстве случаев проходит с первой попытки. Ценность не в том что вывод идеален, а в том что рабочий скелет готов за две минуты вместо тридцати.
Запуск codegen против lab.becomeqa.com
Запускаем codegen против любого URL:
npx playwright codegen https://lab.becomeqa.comОдновременно открываются два окна. Первое: стандартный браузер Chromium с целевой страницей. Второе: Playwright Inspector, отдельное окно с панелью кода, кнопкой записи и подборщиком локаторов.
Специальный проект для этого не нужен. Codegen работает полностью вне Playwright-проекта. Если находишься в директории проекта, сгенерированный код соответствует языку настроенному там. Если нет: по умолчанию TypeScript.
Генерация кода на конкретном языке:
# JavaScript
npx playwright codegen --target javascript https://lab.becomeqa.com
# Python
npx playwright codegen --target python https://lab.becomeqa.com
# Java
npx playwright codegen --target java https://lab.becomeqa.comВыбор конкретного браузера вместо Chromium по умолчанию:
npx playwright codegen --browser firefox https://lab.becomeqa.com
npx playwright codegen --browser webkit https://lab.becomeqa.comФлаг --browser полезен когда подозреваешь что локаторы отличаются между Chromium и WebKit, или когда строишь тест который специфически нацелен на поведение Firefox.
Интерфейс codegen: три инструмента которые нужно знать
Playwright Inspector даёт три вещи которые стоит понять перед началом записи.
Кнопка Record запускает и останавливает запись. Когда активна (красная), каждое взаимодействие в окне браузера фиксируется как код. Кликни ещё раз чтобы поставить на паузу без закрытия сессии. Это позволяет вручную перейти к труднодостижимому состоянию (открыть модальное окно, уйти на несколько страниц вглубь) и возобновить запись когда там окажешься. Подборщик локаторов (иконка прицела) переключает браузер в режим инспекции. Наводи курсор на любой элемент и Inspector показывает локатор который Playwright сгенерировал бы для него, а также превью сколько элементов совпадает. Зелёный: одно совпадение. Жёлтый: несколько совпадений, локатор неоднозначен и в тесте использоваться не должен. Панель ассёртов (иконка чекбокса) позволяет добавлять ассёрты во время записи. Кликни её, затем кликни элемент в браузере, и codegen вставляет ассёртtoBeVisible() в код. Из появляющегося выпадающего списка можно ассёртить текстовое содержимое или состояние чекбокса. Это одна из самых недооценённых функций: начинающие часто записывают действия но забывают добавить хоть один ассёрт.
Почему codegen выбирает getByRole первым
Когда кликаешь кнопку с подписью «Login», codegen генерирует не page.locator('button.login-btn'), а page.getByRole('button', { name: 'Login' }).
Это намеренно. Стратегия локаторов Playwright расставляет приоритеты в таком порядке:
1. getByRole: совпадение по ARIA-роли и доступному имени
2. getByLabel: для инпутов связанных с label
3. getByPlaceholder: для инпутов с placeholder текстом
4. getByText: для неинтерактивных элементов
5. getByTestId: для элементов с атрибутом data-testid
6. CSS или XPath: последний вариант
getByRole идёт первым из-за устойчивости. CSS-класс кнопки может поменяться когда дизайнер обновит стили. Её позиция в DOM может сдвинуться когда кто-то добавит новую фичу. Но кнопка с подписью «Login» почти всегда остаётся с подписью «Login»: изменить это значит сломать UI для реальных пользователей тоже. Тесты на основе доступных локаторов устойчивее потому что ломаются по тем же причинам которые заметили бы реальные пользователи.
Если codegen генерирует что-то вроде page.locator('.btn-primary'), это сигнал что у элемента нет хорошего доступного имени. Стоит остановиться и спросить себя: можно ли добавить атрибут data-testid этому элементу?
aria-label или убедиться что элемент label правильно связан со своим инпутом. Лучшая доступность и лучшие локаторы тестов происходят из одного источника.Запись полного флоу логина
Вот как записать реальный тест логина против lab.becomeqa.com шаг за шагом.
Запускаем codegen:
npx playwright codegen https://lab.becomeqa.comКогда оба окна открыты и запись активна, выполни такую последовательность в браузере:
1. Кликни кнопку Login в навигации
2. Заполни поле email тестовым аккаунтом
3. Заполни поле пароля
4. Кликни Submit
5. Подожди пока загрузится дашборд
6. Используй подборщик ассёртов чтобы ассёртнуть что что-то на дашборде видимо
После этих шагов панель Inspector показывает примерно следующее:
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('https://lab.becomeqa.com/');
await page.getByRole('button', { name: 'Login' }).click();
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Password').fill('password123');
await page.getByRole('button', { name: 'Submit' }).click();
await expect(page.getByText('My Travel Items')).toBeVisible();
});Кликни кнопку копирования в Inspector, создай файл tests/login.spec.ts и вставь туда. Запускаем:
npx playwright test tests/login.spec.ts --project=chromiumПроходит. Рабочий тест за время одного прохода по флоу логина.
Доводка сгенерированного кода
Код работает, но он не продакшн-качества. Три вещи требуют внимания перед тем как он попадёт в реальный тест-сьют.
Захардкоженные учётные данные. Сгенерированный код содержит реальный email и пароль которые ты вводил. Они не должны попасть в систему контроля версий. Перенеси их в переменные окружения:import { test, expect } from '@playwright/test';
test('user can log in', async ({ page }) => {
await page.goto('/');
await page.getByRole('button', { name: 'Login' }).click();
await page.getByLabel('Email').fill(process.env.TEST_EMAIL!);
await page.getByLabel('Password').fill(process.env.TEST_PASSWORD!);
await page.getByRole('button', { name: 'Submit' }).click();
await expect(page.getByText('My Travel Items')).toBeVisible();
});Если в playwright.config.ts настроен baseURL, замени также захардкоженный URL в page.goto() на '/'.
'test'. Переименуй чтобы описать проверяемое поведение, например 'user can log in with valid credentials'.
Отсутствующие ассёрты. Codegen записывает только действия и те ассёрты которые ты явно добавил. Тест логина должен проверять больше одного: не только то что появляется текст «My Travel Items», но и то что URL изменился или что меню пользователя показывает правильный email. Добавь это вручную.
Повторяющиеся локаторы. Если записал флоу который использует один локатор пять раз, вынеси его в переменную:
const emailInput = page.getByLabel('Email');
await emailInput.fill(process.env.TEST_EMAIL!);На уровне теста это мелочь, но становится критичным когда одни и те же локаторы появляются в нескольких файлах тестов. Вот тогда переходишь к Page Object Model. Не раньше.
Запись в разных браузерах и сохранение в файл
Codegen поддерживает все три браузерных движка Playwright. По умолчанию Chromium. Переключайся на Firefox или WebKit когда нужны локаторы работающие во всех движках или при отладке браузер-специфичного поведения:
npx playwright codegen --browser webkit https://lab.becomeqa.comМожно также сохранять сгенерированный код сразу в файл вместо копирования из панели Inspector:
npx playwright codegen --output tests/login.spec.ts https://lab.becomeqa.comПри использовании --output файл записывается когда закрываешь окно Inspector. Если файл уже существует, перезаписывается. Комбинируй с конкретным целевым языком для генерации тестовых файлов в любом поддерживаемом стеке:
npx playwright codegen --target javascript --output tests/login.spec.js https://lab.becomeqa.comДля команд использующих эмуляцию устройств, codegen поддерживает --device для симуляции мобильных вьюпортов:
npx playwright codegen --device "iPhone 13" https://lab.becomeqa.comБраузер открывается с размером экрана iPhone 13 и правильным user agent. Сгенерированный код включает devices['iPhone 13'] в опциях контекста.
Codegen как исследователь локаторов (без записи тестов)
Одно из самых практичных применений codegen вообще не включает запись полного теста. Иногда нужно просто найти правильный локатор для конкретного элемента и не хочется тратить время на ручную инспекцию DOM.
Запусти codegen, кликни подборщик локаторов и наведи курсор на интересующий элемент. Inspector показывает локатор в реальном времени. А также показывает сколько элементов совпадает: критически важная информация перед тем как зафиксировать локатор в тесте.
npx playwright codegen https://lab.becomeqa.comКогда браузер открылся, нажми кнопку записи чтобы остановить запись и не генерировать ненужный код. Переключись в режим подборщика локаторов и наводи курсор на элементы. Inspector обновляет отображение локатора при переходе между элементами. Можешь вводить в поле локатора чтобы проверять варианты и смотреть сколько элементов совпадает.
Этот рабочий процесс заменяет часы проб и ошибок в тест-раннере. Локатор проверяешь до написания теста, а не после того как он упал.
Ограничения codegen: что он не умеет записывать
Codegen обрабатывает большинство пользовательских взаимодействий: клики, заполнение форм, навигацию, выпадающие списки, чекбоксы, радиокнопки. Есть несколько категорий которые он обрабатывает плохо или не обрабатывает вовсе.
Загрузка файлов. Codegen не умеет записыватьpage.setInputFiles(). Когда кликаешь на файловый инпут и выбираешь файл из файловой системы, codegen может зафиксировать клик но не сам выбор файла. Код загрузки файлов нужно писать вручную.
Drag and drop. HTML drag-and-drop события не транслируются корректно в записи codegen. Сгенерированный код может показывать клик без движения перетаскивания: взаимодействие молча не делает то что ожидается. Используй page.dragAndDrop() или симулируй отдельные события mousedown, mousemove и mouseup для надёжного drag.
Сложные ожидания. Codegen записывает действия в момент их выполнения. Он не записывает неявное мышление которое делаешь как человек («я ждал пока спиннер исчезнет перед нажатием»). В медленных или нестабильных средах сгенерированные тесты могут падать потому что выполняются быстрее чем ожидает UI. Добавляй явные ожидания там где этого требует флоу:
await page.waitForLoadState('networkidle');
await expect(page.getByRole('progressbar')).toBeHidden();context.waitForEvent('page'). Codegen может пропустить новую вкладку полностью.
Аутентифицированные состояния. Codegen не знает о сохранённой аутентификации. Если нужно чтобы тесты стартовали уже залогиненными, используй storageState Playwright для сохранения сессионных кук после однократного логина, затем загружай это состояние в начале каждого теста. Codegen может помочь записать логин один раз, но паттерн storage state нужно настраивать вручную.
OAuth и флоу стороннего входа. Любой флоу с редиректом к внешнему провайдеру идентификации (Google, GitHub, Microsoft) сложно записывать с помощью codegen: локаторы находятся на сторонней странице которую можешь не контролировать. Такие флоу требуют отдельной обработки и часто замокированного OAuth-колбэка вместо прохождения через реального провайдера.
FAQ
Код от codegen можно коммитить напрямую?
Редко. Это быстрая отправная точка, не готовый тест. Всегда переименовывай тест, убирай захардкоженные учётные данные, проверяй что ассёрты осмысленные, и убеждайся что локаторы соответствуют структуре доступности страницы.
Можно запускать codegen против localhost?
Да. npx playwright codegen http://localhost:3000 работает точно так же. Если приложение требует аутентификации для доступа к странице которую хочешь записать, залогинься вручную до нажатия кнопки записи.
Codegen сгенерировал CSS-селектор вместо getByRole. Использовать его?
Только если нет лучшего варианта. CSS-селектор вроде .item-card:nth-child(2) сломается как только изменится вёрстка страницы. Попробуй понять почему Playwright откатился к CSS: у элемента скорее всего нет доступного имени. Если добавить нельзя, getByTestId с атрибутом data-testid: следующий лучший вариант.
Codegen замедляет браузер?
Измеримой разницы нет. Запись происходит в процессе Inspector, не внутри самого браузера.
Можно ли ставить запись на паузу в середине и вручную навигировать?
Да. Кликни кнопку записи чтобы поставить на паузу, перейди в нужное состояние, затем кликни запись чтобы возобновить. Фиксируются только взаимодействия когда запись активна.
Почему codegen сгенерировал page.locator('text=Submit') вместо getByRole?
Это происходит когда Playwright не может найти надёжный локатор на основе ролей. Откатывается к совпадению по тексту. Проверь является ли элемент кнопкой с доступным именем: для стандартного элемента button должно генерироваться getByRole('button', { name: 'Submit' }).