Профессиональная автоматизация на Playwright: от миграции к продвинутой архитектуре

Курс предназначен для инженеров по автоматизации, переходящих с Selenium и Cypress. Вы изучите архитектурные преимущества Playwright, освоите современные паттерны проектирования тестов и научитесь эффективно переносить существующие фреймворки на новый стек.

1. Основы Playwright и стратегия миграции с Selenium и Cypress

Основы Playwright и стратегия миграции с Selenium и Cypress

Когда крупный финтех-проект решает перевести три тысячи автотестов с Selenium на Playwright, основным драйвером становится не мода, а экономика. В одном из реальных кейсов переход позволил сократить время прохождения регрессионного цикла с шести часов до сорока минут, одновременно снизив процент «флакующих» (нестабильных) падений с до . Такая разница обусловлена не просто «быстрым движком», а фундаментальной сменой парадигмы взаимодействия с браузером. Если Selenium проектировался в эпоху, когда веб-страница была статичным набором HTML-документов, то Playwright создан для мира высокодинамичных SPA-приложений, где элементы появляются и исчезают в ответ на асинхронные события.

Архитектурный разрыв: почему старые подходы не работают

Главная проблема Selenium заключается в протоколе JSON Wire (или более современном W3C WebDriver). Это синхронный HTTP-протокол: каждый раз, когда тест хочет кликнуть по кнопке, он отправляет HTTP-запрос к драйверу, тот транслирует его браузеру, получает ответ и возвращает его тесту. Это создает накладные расходы на сетевое взаимодействие и, что критичнее, делает невозможным мгновенную реакцию на изменения в DOM.

Playwright использует принципиально иной путь — протокол WebSocket. У него есть постоянное двустороннее соединение с браузером через Chrome DevTools Protocol (CDP) или аналогичные механизмы в Firefox и WebKit.

| Характеристика | Selenium | Cypress | Playwright | | :--- | :--- | :--- | :--- | | Связь | HTTP (запрос-ответ) | Внутри браузера (JS injection) | WebSocket (событийная модель) | | Ожидания | Ручные (Explicit/Implicit) | Автоматические (ограниченные) | Встроенные (Auto-waiting) | | Многостраничность | Сложно (переключение окон) | Ограничено (один таб) | Нативно (Browser Contexts) | | Языки | Java, Python, C#, JS, Ruby | JavaScript / TypeScript | JS, TS, Python, Java, C# |

В отличие от Cypress, который запускает тесты внутри того же цикла событий (Event Loop), что и само приложение, Playwright остается внешним инструментом. Это избавляет его от «родовых травм» Cypress: проблем с кросс-доменными переходами, iframe и необходимостью «взламывать» браузер для выполнения определенных действий.

Изоляция через Browser Contexts

Одной из самых мощных концепций Playwright является разделение на три уровня: Browser, Browser Context и Page. В традиционных фреймворках для изоляции тестов нам приходилось либо закрывать и открывать браузер целиком (что крайне медленно), либо чистить куки и локальное хранилище вручную (что ненадежно).

Playwright вводит понятие контекста — это своего рода «инкогнито-сессия». Создание нового контекста занимает миллисекунды и потребляет минимум ресурсов, так как экземпляр браузера (бинарный процесс) уже запущен.

> Browser Context — это изолированная среда внутри одного экземпляра браузера. У каждого контекста свои куки, локальное хранилище и кэш. Это позволяет запускать десятки тестов параллельно в одном браузере, не боясь, что они повлияют друг на друга.

Представьте сценарий: вам нужно протестировать чат между двумя пользователями. В Selenium вам пришлось бы запускать два разных драйвера. В Playwright это выглядит так:

  • Создаем context1 для Алисы, логинимся.
  • Создаем context2 для Боба, логинимся.
  • В рамках одного теста оперируем двумя страницами, проверяя доставку сообщений в реальном времени.
  • Стратегия миграции: от императивного к декларативному

    Переход с Selenium — это не просто замена driver.findElement() на page.locator(). Это отказ от ручного управления ожиданиями. В Selenium типичный код выглядит так:

    В Playwright вы пишете просто:

    Playwright сам выполнит серию проверок (Actionability checks) перед кликом:

  • Виден ли элемент?
  • Стабилен ли он (не движется ли в данный момент анимация)?
  • Не перекрыт ли он другим элементом?
  • Включен ли он (Enabled)?
  • Если вы попытаетесь перенести старую логику «сна» (Thread.sleep или time.sleep) в Playwright, вы уничтожите все его преимущества. Первым шагом миграции должен стать аудит всех явных ожиданий.

    Этап 1: Обертки и адаптеры

    На начальном этапе миграции часто создают тонкий слой абстракции, который имитирует привычный синтаксис Selenium, но под капотом использует Playwright. Это позволяет перевести инфраструктуру (запуск, отчеты, CI/CD) без переписывания всех тестов сразу. Однако задерживаться на этом этапе нельзя — вы получите «Selenium на стероидах», но не полноценный Playwright.

    Этап 2: Переход на Locators

    В Playwright селекторы стали «умными». Рекомендуется уходить от хрупких XPath и CSS-путей в сторону пользовательских атрибутов или текстовых соответствий. Например, page.getByRole('button', { name: 'Войти' }) гораздо устойчивее к изменениям верстки, чем //div[2]/button[1].

    Работа с сетевым уровнем

    В Cypress перехват запросов (intercept) был киллер-фичей. В Selenium это требовало использования прокси-серверов (например, BrowserMob Proxy). Playwright предоставляет нативный API для работы с сетью.

    Это критически важно при миграции тестов, которые зависят от внешних данных. Вы можете «замокать» ответ API одной строчкой:

    Это позволяет тестировать фронтенд в изоляции от нестабильного бэкенда, что является стандартом в современной автоматизации.

    Тонкости параллелизации и ресурсов

    При переходе с Selenium Grid на встроенную параллелизацию Playwright важно пересмотреть подход к ресурсам. Playwright по умолчанию запускает тесты в несколько потоков (workers). Если ваш старый фреймворк полагался на то, что тесты идут по порядку или используют общие статические данные в коде, миграция выявит эти архитектурные ошибки.

    Каждый воркер в Playwright — это отдельный процесс ОС. Это обеспечивает максимальную изоляцию, но требует понимания того, как распределяется нагрузка на CPU. Оптимальная формула для CI обычно составляет:

    Это позволяет избежать перегрузки системы, при которой тесты начинают падать по таймауту из-за нехватки процессорного времени на отрисовку браузера.

    Сравнение механизмов ожидания

    Рассмотрим математическую модель надежности теста. Пусть — вероятность успешного прохождения шага. В Selenium она часто зависит от внешнего фактора (времени ожидания). Если слишком мало, тест падает. Если слишком велико, тесты идут долго.

    Playwright минимизирует зависимость от , используя событийную модель. Вместо того чтобы опрашивать DOM каждые 500 мс (как это делает Selenium), Playwright подписывается на события браузера. Это позволяет достичь теоретического максимума скорости выполнения: действие совершается ровно в тот момент, когда браузер к нему готов.

    Практические рекомендации по началу миграции

  • Не мигрируйте всё сразу. Начните с «зеленой зоны» — новых фич. Пишите их на Playwright, запуская параллельно со старым сьютом.
  • Используйте Codegen для обучения. Утилита npx playwright codegen генерирует код на основе ваших действий в браузере. Для опытного автоматизатора это плохой способ писать тесты, но отличный способ быстро выучить синтаксис локаторов.
  • Пересмотрите Page Object Model. В Playwright классический POM часто дополняется фикстурами. Вместо инициализации страниц в каждом тесте:
  • const loginPage = new LoginPage(page); вы будете использовать внедрение зависимостей через фикстуры, что сделает код чище.

    Миграция на Playwright — это не просто смена библиотеки, это переход к событийному тестированию. Главный вызов здесь — не технический синтаксис, а изменение ментальной модели автоматизатора: от контроля каждого микродвижения браузера к декларативному описанию желаемого состояния.

    2. Современные селекторы и механизмы автоматического ожидания элементов

    Современные селекторы и механизмы автоматического ожидания элементов

    Почему тесты на Selenium часто называют «хрупкими»? Основная причина кроется в рассинхронизации между скоростью выполнения скрипта и скоростью рендеринга веб-страницы. Традиционный подход заставлял инженеров вручную прописывать ожидания (Explicit Waits) или, что еще хуже, использовать Thread.sleep(), превращая код в нагромождение костылей. Playwright радикально меняет правила игры, внедряя концепцию «умных» локаторов и встроенных проверок готовности элементов.

    Философия локаторов: переход от DOM к пользовательскому опыту

    В автоматизации старой школы мы привыкли опираться на структуру документа: XPath, CSS-селекторы, ID. Но структура DOM изменчива. Дизайнер может заменить <div> на <span> или обернуть кнопку в дополнительный контейнер, и ваш селектор //div[@id='submit-btn']/span мгновенно превратится в тыкву.

    Playwright продвигает методологию тестирования через призму доступности (Accessibility). Вместо того чтобы искать «синюю кнопку с классом .btn-primary», мы ищем «кнопку с текстом "Отправить"». Это делает тесты более устойчивыми к рефакторингу фронтенда и заставляет разработчиков следовать стандартам ARIA, что полезно для доступности продукта.

    Ролевая модель и текстовые ориентиры

    Основным инструментом поиска в Playwright являются методы getBy*. Они спроектированы так, чтобы имитировать поведение реального пользователя.

  • getByRole: Самый мощный и рекомендуемый метод. Он ищет элементы по их семантической роли в дереве доступности.
  • Здесь name — это не атрибут name, а доступное имя (accessible name), которое может браться из текста кнопки, атрибута aria-label или title. Если верстка изменится с <button> на <div role="button">, тест продолжит работать.

  • getByText: Идеален для поиска статического контента. По умолчанию поиск ведется по частичному совпадению, но его можно настроить на строгое соответствие.
  • getByPlaceholder, getByLabel, getByAltText: Эти методы напрямую связывают тест с элементами форм и изображениями. Если вы тестируете форму регистрации, использование getByLabel('Электронная почта') гарантирует, что поле ввода правильно связано с его подписью через атрибут for.
  • Когда без CSS и XPath не обойтись

    Несмотря на приоритет пользовательских локаторов, в сложной корпоративной верстке (например, в таблицах данных с тысячами ячеек или в legacy-системах) иногда приходится использовать технические селекторы. Playwright поддерживает их нативно:

  • page.locator('css=.my-class') или просто page.locator('.my-class').
  • page.locator('xpath=//header//input') или page.locator('//header//input').
  • Однако хорошей практикой считается использование атрибутов для тестирования, таких как data-testid. Для этого в Playwright есть специальный метод getByTestId().

    Механика Actionability: как работает автоматическое ожидание

    Главное преимущество Playwright — отсутствие необходимости в явных ожиданиях перед каждым действием. Когда вы вызываете await page.click('.submit'), фреймворк не просто пытается нажать на координаты. Он запускает цикл проверок готовности элемента, называемый Actionability Checks.

    Алгоритм проверки перед действием

    Прежде чем выполнить клик или ввод текста, Playwright проверяет, соответствует ли элемент следующим критериям:

  • Attached: Элемент присутствует в DOM-дереве.
  • Visible: Элемент имеет ненулевой размер и не скрыт через display: none или visibility: hidden.
  • Stable: Элемент не находится в процессе анимации (его позиция не меняется на протяжении нескольких кадров).
  • Enabled: Элемент не заблокирован атрибутом disabled.
  • Receives Events: Элемент не перекрыт другими элементами (например, модальным окном или лоадером).
  • Если условия не соблюдены, Playwright будет повторять проверку до истечения таймаута (по умолчанию 30 секунд). Это устраняет 90% проблем с «мигающими» (flaky) тестами, вызванными медленной загрузкой скриптов или анимациями.

    Нюансы стабильности и перекрытия

    Рассмотрим ситуацию: вы нажимаете кнопку «Сохранить», и поверх страницы на доли секунды появляется полупрозрачный оверлей загрузки. Selenium в такой ситуации может выкинуть ElementClickInterceptedException. Playwright же «дождется», пока оверлей исчезнет, и только потом нажмет на кнопку.

    Однако стоит учитывать, что проверки различаются в зависимости от действия. Например:

  • Для click() важны все 5 пунктов.
  • Для fill() (ввод текста) проверка на перекрытие (Receives Events) не проводится, так как ввод в input часто возможен, даже если он частично прикрыт декоративным элементом.
  • Продвинутая работа с локаторами: фильтрация и вложенность

    В реальных интерфейсах мы часто сталкиваемся с повторяющимися элементами. Например, список карточек товаров, в каждой из которых есть кнопка «Купить». Как нажать кнопку именно во второй карточке?

    Цепочки локаторов (Chaining)

    Локаторы в Playwright можно комбинировать, сужая область поиска. Каждое последующее звено ищет внутри результата предыдущего.

    Этот подход гораздо надежнее, чем сложные XPath-выражения типа //div[contains(@class, "product-item") and contains(., "iPhone 15")]//button.

    Фильтрация по состоянию и вложенным элементам

    Метод .filter() позволяет отсеивать элементы не только по тексту, но и по наличию внутри них других элементов.

    Это критически важно при работе с динамическими списками, где индексы элементов могут меняться. Вместо nth(2) (взять второй элемент), который крайне нестабилен, лучше использовать фильтрацию по уникальному признаку внутри контейнера.

    Списки и множественные элементы

    Иногда нам нужно совершить действие со всеми элементами сразу или проверить их количество. Playwright предоставляет для этого удобные инструменты, но предостерегает от использования циклов for с индексами.

    Метод all() и count()

    Если вам нужно получить массив локаторов для итерации:

    Метод all() возвращает массив локаторов, которые уже «привязаны» к своим позициям, что позволяет безопасно работать с ними, даже если DOM меняется во время итерации.

    Ожидание исчезновения

    Часто нужно дождаться не появления, а исчезновения элемента (например, спиннера загрузки). В Playwright это реализуется через утверждения (assertions) или специальные настройки ожидания:

    Здесь вступает в дело механизм Web-First Assertions. В отличие от обычных проверок, они сами умеют ждать выполнения условия. Если вы напишете expect(await page.isVisible('.loader')).toBe(false), тест упадет мгновенно, если лоадер еще на экране. Но await expect(page.locator('.loader')).toBeHidden() будет опрашивать страницу, пока условие не выполнится.

    Математика таймаутов и производительность

    Playwright использует иерархическую систему таймаутов. Важно понимать, как они взаимодействуют, чтобы не создавать «вечно висящие» тесты.

    Пусть — общий таймаут теста, — таймаут конкретного действия (click, fill), а — таймаут утверждения.

    Где:

  • обычно настраивается в конфиге (testConfig.timeout).
  • по умолчанию равен 30 секундам.
  • по умолчанию равен 5 секундам.
  • Если ваше приложение работает медленно, не стоит увеличивать глобальный таймаут до бесконечности. Лучше точечно настроить ожидание для «тяжелых» операций:

    Практические советы по миграции селекторов

    При переносе тестов с Selenium на Playwright следуйте алгоритму «от простого к сложному»:

  • Замените ID и CSS на Роли: Вместо driver.findElement(By.id("login-btn")) используйте page.getByRole('button', { name: 'Login' }).
  • Избавьтесь от Wait-хелперов: Удалите все WebDriverWait и ExpectedConditions. Playwright сделает это лучше под капотом.
  • Используйте константы для локаторов: В Playwright локатор — это не найденный элемент, а описание того, как его найти. Вы можете объявить const loginBtn = page.getByRole('button') в начале теста, и поиск произойдет только в момент вызова await loginBtn.click(). Это позволяет легко реализовывать паттерн Page Object.
  • Использование современных локаторов не только сокращает объем кода, но и делает его самодокументированным. Читая page.getByLabel('Password').fill('12345'), любой член команды (даже не автоматизатор) понимает, что происходит в тесте. Это и есть профессиональный подход к автоматизации: создание надежных, читаемых и легко поддерживаемых инструментов контроля качества.

    3. Архитектура тестового фреймворка: использование фикстур и жизненный цикл тестов

    Архитектура тестового фреймворка: использование фикстур и жизненный цикл тестов

    Представьте, что вы строите сложный механизм, где каждая деталь должна быть идеально чистой перед сборкой, а после испытаний — мгновенно заменена на новую, чтобы не вносить погрешность в следующий запуск. В традиционных инструментах вроде Selenium автоматизаторы годами сражались с глобальным состоянием, создавая громоздкие иерархии классов BaseTest и перегружая методы setUp и tearDown. Playwright предлагает принципиально иной подход, заимствованный из функционального программирования и лучших практик Dependency Injection: механизм фикстур. Это не просто «подготовка данных», а фундамент архитектуры, который позволяет тестам быть атомарными, быстрыми и невероятно гибкими.

    Отказ от классического наследования в пользу композиции

    В Selenium-фреймворках доминирует паттерн наследования. У вас есть BaseTest, от него наследуется LoginTest, от того — DashboardTest. Если на уровне DashboardTest вам внезапно понадобилось изменить логику инициализации драйвера, вы рискуете сломать всю цепочку. Кроме того, параллелизация в такой схеме часто превращается в кошмар из-за разделяемых статических переменных.

    Playwright перечеркивает эту зависимость. Вместо того чтобы «наследовать» окружение, тест «запрашивает» его. Фикстуры в Playwright — это изолированные объекты или функции, которые передаются в тестовый метод в качестве аргументов.

    В этом примере profilePage и settingsPage — это фикстуры. Тесту не важно, как они созданы, как инициализировался браузер или как очищались куки. Он просто потребляет готовые сущности. Если фикстура не указана в аргументах, она не будет запущена, что экономит ресурсы. Это и есть модульная архитектура: вы собираете окружение теста как конструктор Lego.

    Анатомия фикстуры и инверсия управления

    Фикстура в Playwright — это асинхронная функция, которая использует специальный аргумент use. Это ключевое отличие от обычных функций-хелперов. Когда вы вызываете use(value), выполнение теста приостанавливается в этой точке, передавая value внутрь теста. После завершения теста выполнение фикстуры возобновляется со строки, следующей за use. Это позволяет элегантно реализовывать очистку данных (teardown) в том же месте, где происходила подготовка (setup).

    Рассмотрим создание фикстуры для административной панели, которая требует предварительной авторизации через API:

    Здесь проявляется принцип инверсии управления (IoC). Тест не управляет жизненным циклом adminPage, он лишь декларирует потребность в ней. Playwright сам определит порядок инициализации зависимостей. Если adminPage зависит от другой фикстуры, например databaseConnection, фреймворк сначала создаст соединение с базой, затем страницу, выполнит тест и закроет всё в обратном порядке.

    Уровни изоляции: Worker vs Test

    Одной из самых мощных и одновременно опасных возможностей является управление областью видимости (scope) фикстур. Playwright разделяет их на два типа:

  • Test Scope (по умолчанию): Фикстура создается заново для каждого теста. Это гарантирует максимальную изоляцию. Если один тест удалил запись в UI, другой тест этого не заметит, так как у него будет свой контекст браузера.
  • Worker Scope: Фикстура создается один раз для процесса (воркера) и переиспользуется всеми тестами, которые в нем запускаются.
  • Зачем нужен Worker Scope? Представьте, что ваш проект требует тяжелой инициализации: поднятия Docker-контейнера, генерации огромного кеша или сложной настройки глобального состояния БД. Делать это перед каждым тестом — значит увеличить время прогона в десятки раз.

    Важно помнить о «законе сохранения энтропии»: используя воркер-фикстуры для ускорения, вы берете на себя ответственность за то, что тесты не будут мешать друг другу. Если тест изменил данные в globalDb, тест должен уметь работать с этими изменениями или откатывать их.

    Жизненный цикл и автоматические фикстуры

    Иногда нам нужно выполнить код перед каждым тестом, но при этом мы не хотим явно прописывать аргумент в каждом методе test(...). Например, это может быть сбор логов, мониторинг сетевых ошибок или внедрение скриптов аналитики. Для этого существуют auto-фикстуры.

    ``javascript export const test = base.extend({ errorMonitor: [async ({ page }, use) => { const errors = []; page.on('pageerror', (err) => errors.push(err));

    await use(null); // Тесту не нужен этот объект напрямую

    if (errors.length > 0) { throw new Error(Обнаружены ошибки в консоли: T_{total}nT_{setup}n=100T_{setup}ABBA$, Playwright выдаст ошибку на этапе парсинга.

    Еще один нюанс — работа с несколькими контекстами. Если ваш тест имитирует взаимодействие двух пользователей (например, отправитель и получатель в мессенджере), вы можете создать две независимые фикстуры userA и userB, каждая из которых будет владеть собственным объектом browserContext. Это обеспечивает полную изоляцию сессий на уровне сетевых запросов и хранилища, что практически невозможно было реализовать в Cypress без костылей и было крайне медленно в Selenium.

    Также стоит учитывать, что фикстуры могут возвращать не только объекты, но и функции (фабрики). Это полезно, если вам нужно создавать сущности с динамическими параметрами внутри теста, но вы хотите сохранить логику их создания в слое архитектуры, а не в теле теста.

    Замыкание архитектурного цикла

    Использование фикстур превращает тестовый фреймворк из набора разрозненных скриптов в стройную экосистему. Мы уходим от императивного стиля («сначала сделай это, потом то») к декларативному («мне нужен авторизованный пользователь и открытая корзина»). Это не только повышает читаемость, но и делает тесты устойчивыми к изменениям. Если завтра способ авторизации изменится с формы логина на OAuth2, вам придется поправить только одну фикстуру, а сотни тестов продолжат работать без единого изменения в их коде.

    Такой подход требует дисциплины: нужно вовремя выносить общую логику в фикстуры и следить за тем, чтобы они оставались максимально атомарными. Но инвестиции в эту архитектуру окупаются мгновенно, как только проект вырастает за пределы десяти тестов.

    4. Тестирование сложных пользовательских сценариев и интеграция с API

    Тестирование сложных пользовательских сценариев и интеграция с API

    Представьте, что вы тестируете банковское приложение. Чтобы проверить перевод средств, вам нужно: создать пользователя, подтвердить его email, пополнить баланс через эквайринг, совершить перевод и убедиться, что в базе данных и в истории операций суммы сошлись. Если выполнять каждый шаг через графический интерфейс (UI), тест превратится в десятиминутное «путешествие», которое будет падать при малейшем изменении верстки на этапе регистрации. В Playwright решение этой проблемы строится не на обходе ограничений браузера, а на глубокой гибридной интеграции UI и API, где браузер и сетевой уровень работают как единый механизм.

    Гибридный подход: зачем смешивать UI и API

    Основная проблема классических UI-тестов в Selenium — их линейность и хрупкость. Playwright предлагает парадигму, в которой UI используется только для проверки того, что действительно важно пользователю на конкретной странице, а все подготовительные действия (Preconditions) и проверки состояния системы (Assertions) выносятся на уровень API-запросов.

    Этот подход решает три критические задачи:

  • Скорость. Создание сущности через POST-запрос занимает 50–200 мс, в то время как заполнение формы в браузере — от 3 до 10 секунд.
  • Стабильность. API-контракты меняются реже, чем селекторы на фронтенде.
  • Атомарность. Вы можете тестировать страницу редактирования профиля, не проходя каждый раз через флоу авторизации и поиска этого профиля в списках.
  • В Playwright встроенный объект request позволяет отправлять HTTP-запросы в контексте текущего браузера. Это означает, что если вы авторизованы в браузере, ваши API-запросы автоматически будут использовать те же куки и токены, что и открытая страница.

    Перехват и модификация сетевого трафика

    Одной из самых мощных функций Playwright является метод page.route(). Он позволяет перехватывать сетевые запросы, которые инициирует браузер, и изменять их «на лету» или подменять ответы (Mocking).

    Это критически важно для тестирования сложных сценариев, которые трудно воспроизвести в реальности: * Ошибки сервера (, , ). * Задержки сети для проверки лоадеров и скелетонов. * Изменение прав доступа пользователя без перелогина.

    Рассмотрим пример, где нам нужно проверить, как интерфейс реагирует на пустой список заказов, хотя в тестовой базе у пользователя их сотни. Вместо очистки базы данных мы просто подменяем ответ от API:

    Метод route.fulfill() позволяет не только подменять тело ответа, но и устанавливать статус-коды или заголовки. Если же нам нужно проверить реальные данные, но с небольшой модификацией (например, изменить дату в одном из объектов), мы можем использовать route.fetch():

    Здесь route.fetch() выполняет реальный запрос к серверу, получает результат, а затем мы модифицируем его и отдаем браузеру. Это позволяет тестировать «краевые состояния» логики фронтенда, не меняя состояние бэкенда.

    Тестирование сложных состояний через API-фикстуры

    В предыдущих разделах мы обсуждали фикстуры как способ инициализации страниц. В сложных сценариях фикстуры превращаются в «фабрики данных». Вместо того чтобы в каждом тесте писать логику создания заказа, мы создаем фикстуру, которая возвращает уже готовый объект, созданный через API.

    Представим сценарий: «Пользователь может отменить заказ в статусе "Ожидает обработки"».

  • Фикстура order отправляет POST-запрос на /api/orders.
  • Получает ID созданного заказа.
  • Передает этот ID в тест.
  • Тест открывает страницу page.goto('/orders/' + order.id).
  • После завершения теста фикстура (в блоке после yield или через use) отправляет DELETE-запрос для очистки данных.
  • Такая архитектура делает тесты независимыми. Если создание заказа через UI сломается, упадут только тесты на «Создание заказа». Тесты на «Отмену заказа» продолжат работать, так как они создают данные через API, минуя сломанный UI-компонент.

    Работа с Iframe и Shadow DOM в сложных сценариях

    Современные веб-приложения часто используют сторонние виджеты (платежные формы, чаты, карты), которые инкапсулированы в iframe. В Selenium работа с ними требовала явного переключения контекста через switchTo(). В Playwright работа с фреймами бесшовная благодаря объекту FrameLocator.

    Playwright автоматически дожидается появления фрейма и готовности элементов внутри него. Аналогично обстоит дело с Shadow DOM. В отличие от других инструментов, Playwright «видит» элементы внутри открытых Shadow Roots по умолчанию. Вам не нужно использовать специальные селекторы или проникать вглубь дерева через JavaScript — обычные getByRole или CSS-селекторы будут работать сквозь границы Shadow DOM, если они не закрыты (closed mode).

    Синхронизация UI и API: ожидание завершения фоновых процессов

    Частая ошибка при переходе с Selenium — попытка использовать page.waitForTimeout(3000) после клика на кнопку «Сохранить». В сложных сценариях изменения могут происходить асинхронно. Playwright предоставляет элегантный способ дождаться конкретного сетевого события:

    Использование Promise.all гарантирует, что мы начнем слушать сеть до того, как нажмем на кнопку. Если нажать кнопку сначала, запрос может улететь и завершиться быстрее, чем включится ожидание, что приведет к зависанию теста. Этот метод позволяет извлечь данные из ответа сервера (например, сгенерированный UUID) и использовать их в следующих шагах теста.

    Эмуляция устройств и геолокации

    Сложные сценарии часто включают проверку адаптивности или логики, зависящей от местоположения пользователя. Playwright позволяет переопределять контекст браузера «на лету».

    Если ваше приложение показывает разные цены для пользователей из США и Европы, вам не нужен VPN. Достаточно настроить контекст:

    Это позволяет тестировать мобильную версию сайта с имитацией реального устройства и координат в рамках одного тестового запуска. Важно помнить, что такие настройки лучше выносить на уровень конфигурации проекта (playwright.config.ts), чтобы запускать одни и те же сценарии в разных «проектах» (например, Desktop Chrome и Mobile Safari).

    Обработка диалогов и всплывающих окон

    В сложных сценариях часто встречаются нативные браузерные диалоги: alert, confirm или prompt. Playwright по умолчанию автоматически закрывает их (отменяет), чтобы тест не завис. Однако, если вам нужно нажать «ОК» или проверить текст сообщения, необходимо зарегистрировать обработчик:

    Ключевой момент: обработчик события dialog должен быть объявлен до совершения действия, которое вызывает этот диалог.

    Управление состоянием: Storage State

    При миграции с Selenium разработчики часто сталкиваются с проблемой: каждый тест начинается с чистой страницы, и нужно заново проходить логин. В Playwright есть механизм storageState, который позволяет один раз авторизоваться, сохранить куки и localStorage в JSON-файл, а затем подкладывать этот файл во все последующие тесты.

    Это экономит минуты в каждом тестовом прогоне. В сложных сценариях вы можете подготовить несколько файлов состояния: admin.json, customer.json, guest.json.

    Теперь каждый тест, использующий этот контекст, будет открываться уже в авторизованном состоянии. Это позволяет фокусироваться на бизнес-логике сценария, а не на инфраструктурных повторах.

    Замыкание логики: проверка побочных эффектов

    Завершая сложный сценарий, профессиональный автоматизатор всегда проверяет не только то, что «кнопка нажалась», но и то, что данные корректно сохранились в системе. Комбинируя request и page, мы можем реализовать паттерн «UI Action -> API Verification».

    Например, после смены пароля в интерфейсе, мы можем отправить запрос на API авторизации с новым паролем прямо внутри теста, чтобы убедиться, что бэкенд действительно принял изменения. Это создает «двойное кольцо» проверки, исключая ситуации, когда фронтенд просто нарисовал успешное уведомление, но фактически запрос в базу данных не ушел или завершился с ошибкой, которую интерфейс проигнорировал.

    Интеграция API в UI-тесты — это не просто бонус, это стандарт индустрии для создания быстрых и надежных фреймворков. Playwright делает эту интеграцию естественной, предоставляя инструменты для управления трафиком, состоянием и данными «из коробки».

    5. Инструменты отладки, визуализация выполнения и генерация профессиональных отчетов

    Инструменты отладки, визуализация выполнения и генерация профессиональных отчетов

    Представьте ситуацию: тест падает в CI/CD на 145-м шаге сложного сценария оформления заказа. Логи показывают лаконичное «Timeout exceeded», но локально на вашей машине всё проходит идеально. В Selenium вы бы добавили десятки скриншотов или пытались воспроизвести условия через удаленную отладку. В Playwright решение этой задачи занимает тридцать секунд благодаря Trace Viewer — инструменту, который позволяет буквально «отмотать время назад» и исследовать состояние DOM, сетевые запросы и консольные логи в момент падения.

    Анатомия Trace Viewer: машина времени для автотестов

    Trace Viewer — это не просто запись экрана. Это полноценный слепок выполнения теста, который сохраняется в файл с расширением .zip. В отличие от видеозаписи, трейс интерактивен: вы можете инспектировать элементы, проверять CSS-свойства и видеть, как именно Playwright «видел» страницу в каждую миллисекунду выполнения.

    Как работает механизм записи трассировки

    Для активации записи в конфигурационном файле playwright.config.ts используется параметр trace. Наиболее эффективная стратегия для профессиональных проектов — режим on-first-retry. Это позволяет не тратить ресурсы на запись успешных тестов, но получать полную диагностику при повторном падении.

    Когда трейс открыт, интерфейс разделяется на несколько ключевых зон:

  • Timeline (Шкала времени): Позволяет навести курсор на любой момент теста. Вы увидите «красные точки» — моменты совершения действий (клики, ввод текста).
  • Actions (Список действий): Слева отображается лог всех команд Playwright. При выборе действия Trace Viewer показывает состояние страницы до (Before) и после (After) его выполнения.
  • Snapshot (Снимок DOM): Центральная часть — это живой DOM. Вы можете открыть консоль разработчика прямо внутри трейса и проверить селектор.
  • Call Stack и Metadata: Здесь видно, в какой строке кода был вызван метод и сколько времени заняло каждое действие (включая Actionability checks).
  • Особую ценность представляет вкладка Network. Если тест упал из-за того, что API-запрос вернул ошибку или , вы увидите это мгновенно, не копаясь в логах сервера. Это делает Trace Viewer незаменимым инструментом при отладке «флакующих» (нестабильных) тестов, где причина часто кроется в гонке условий между фронтендом и бэкендом.

    Интерактивная отладка через Playwright Inspector

    Если Trace Viewer идеален для посмертного анализа в CI, то Playwright Inspector — это основной инструмент «живой» разработки. Он запускается при использовании флага --debug или метода page.pause().

    В режиме инспектора выполнение теста приостанавливается, и открывается дополнительное окно управления. Главное преимущество здесь — Locator Picker. Вы нажимаете на кнопку в браузере, а инспектор генерирует наиболее устойчивый локатор, используя приоритеты (getByRole, getByText), которые мы обсуждали в предыдущих главах.

    Продвинутые техники отладки в VS Code

    Для тех, кто предпочитает не выходить из IDE, расширение Playwright для VS Code предлагает уникальный функционал: * Live Editing: Вы можете менять код теста прямо во время паузы на брейкпоинте, и Playwright подхватит изменения без перезапуска браузера. * Step-by-step Execution: Пошаговое выполнение с подсветкой текущего локатора прямо в окне браузера. * Pick Locator: Генерация селектора сразу в код теста.

    Интересный нюанс: при отладке в VS Code вы можете включить режим «Show Browser». Playwright будет подсвечивать каждый элемент, с которым взаимодействует, в реальном времени. Если локатор находит несколько элементов, Playwright выделит их все, помогая вам понять, почему тест кликает «не туда».

    Генерация и кастомизация отчетов

    Отчеты в Playwright — это не просто список «Passed/Failed». Это инструмент коммуникации между автоматизатором, разработчиком и QA-менеджером. По умолчанию фреймворк предлагает несколько типов репортеров: list, line, dot, json, junit и самый мощный — html.

    HTML-репортер: стандарт индустрии

    HTML-отчет Playwright автономен. Он генерирует папку playwright-report, которую можно открыть в любом браузере. В него автоматически встраиваются: * Скриншоты падений. * Видео выполнения (если включено). * Ссылки на Trace Viewer. * Логи консоли браузера и stdout теста.

    Для крупных проектов стандартного отчета бывает недостаточно. Например, когда нужно сгруппировать тесты по функциональным модулям или связать их с ID в Jira. В таких случаях используется кастомизация через метаданные.

    Интеграция с Allure Framework

    Хотя встроенный HTML-репортер хорош, Allure остается стандартом для кросс-платформенной отчетности. Playwright имеет нативную поддержку Allure через плагин allure-playwright.

    Использование test.step внутри тестов критически важно для визуализации. В отчете (как в HTML, так и в Allure) тест превращается в иерархическую структуру. Вместо полотна из 50 строк кода вы видите логические блоки: «Авторизация» -> «Добавление товара» -> «Проверка скидки». Это значительно упрощает чтение отчета не-техническими специалистами.

    Визуальное регрессионное тестирование

    Playwright предоставляет встроенные инструменты для сравнения скриншотов, что является частью «визуального отчета». Это позволяет ломать верстку гораздо реже.

    Метод expect(page).toHaveScreenshot() работает по алгоритму попиксельного сравнения. Однако в современных веб-приложениях всегда есть динамические элементы (даты, анимации, рекламные баннеры). Для борьбы с ложноположительными срабатываниями Playwright позволяет настраивать порог чувствительности.

    Если это соотношение меньше заданного threshold, тест считается пройденным.

    При падении такого теста в HTML-отчете появляется специальный слайдер. Он позволяет наложить эталонное изображение на актуальное и увидеть разницу (diff) в виде ярких пятен. Это избавляет от необходимости гадать, что именно изменилось в интерфейсе.

    Мониторинг производительности и сетевых логов в отчетах

    Профессиональный отчет должен отвечать не только на вопрос «Работает ли это?», но и «Как быстро это работает?». Playwright позволяет собирать метрики производительности (Web Vitals) и вкладывать их в отчет.

    Используя фикстуры, можно автоматически собирать данные о времени загрузки страницы:

    Эти данные можно выгружать в JSON-репортер для последующего построения графиков в Grafana или Kibana. Таким образом, ваш тестовый фреймворк превращается в инструмент мониторинга качества продукта на разных этапах CI/CD.

    Работа с логами: от console.log до системных событий

    Часто проблема кроется не в UI, а в скрытых ошибках JavaScript на странице. Playwright позволяет подписываться на события консоли и автоматически добавлять их в отчет при падении теста.

    В конфигурации можно настроить перехват pageerror (необработанные исключения в браузере). Если на странице вылетит ReferenceError, Playwright пометит тест как упавший, даже если все ассерты прошли успешно. Это «строгий» подход к качеству, который предотвращает попадание скрытых багов в продакшен.

    Финальный штрих: Blob-репортеры для параллельных запусков

    В современных пайплайнах тесты часто запускаются на разных машинах (шардинг). Playwright предлагает blob-репортер, который собирает результаты с каждого воркера в промежуточные бинарные файлы. Затем специальная команда npx playwright merge-reports объединяет их в один финальный HTML-отчет. Это решает проблему «разрозненных результатов», когда у вас 10 параллельных джоб в GitLab или GitHub Actions, а отчет нужен один общий.

    Использование этих инструментов в совокупности превращает процесс отладки из гадания на кофейной гуще в точную инженерную дисциплину. Trace Viewer дает контекст, Инспектор — скорость разработки, а кастомизированные отчеты — прозрачность для всей команды.