Puppeteer и Playwright сегодня
Несмотря на то, что у этих фреймворков много общего, Puppeteer и Playwright развивались с разной скоростью, и сейчас Playwright набрал обороты и оставил Puppeteer позади.
Это привело к тому, что многие перешли с Puppeteer на Playwright. Это статья показывает, какие нужны шаги и какие новые возможности открывает этот переход. Пусть вас не смущает объем этой статьи, в большинстве случаев переход происходит быстро и безболезненно.
Зачем нужен переход?
Для полного сравнения инструментов и выявления его плюсов и минусов потребуется отдельная статья (сравнения фреймворков), а для перехода на Playwright вам потребуется мало усилий.
На момент написание статьи, команда Playwright часто и последовательно добавляли крупные изменения в течении некоторого времени, которые изменили рынок автоматизации, а Puppeteer, в свою очередь, выпускал в основном небольшие изменения и исправлял ошибки.
Playwright имеет преимущество в производительности в E2E сценариях, что приводит к меньшему времени выполнения тестов и более быстрому получению результатов.
Тесты Playwright, кажется, работают даже более стабильно, чем их уже надежные аналоги из Puppeteer.
Сообщество Playwright на GitHub, Twitter, Slack очень активное, а сообщество Puppeteer — все тише и тише.
Какие изменения которые надо внести в ваших скрипты — краткая версия
Ниже вы можете найти шпаргалку с командами Puppeteer и аналог команд Playwright.
PUPPETEER |
PLAYWRIGHT |
---|---|
require('puppeteer') |
require('playwright') |
puppeteer.launch(...) |
playwright.chromium.launch(...) |
browser.createIncognitoBrowserContext(...) |
browser.newContext(...) |
page.setViewport(...) |
page.setViewportSize(...) |
page.waitForSelector(selector) page.click(selector); |
page.click(selector) |
page.waitForXPath(XPathSelector) |
page.waitForSelector(XPathSelector) |
page.$x(xpath_selector) |
page.$(xpath_selector) |
page.waitForNetworkIdle(...) |
page.waitForLoadState({ state: 'networkidle' }}) |
page.waitForFileChooser(...) |
Removed handled differently. |
page.waitFor(timeout) |
page.waitForTimeout(timeout) |
page.type(selector, text) |
page.fill(selector, text) |
page.cookies([...urls]) |
browserContext.cookies([urls]) |
page.deleteCookie(...cookies) |
browserContext.clearCookies() |
page.setCookie(...cookies) |
browserContext.addCookies(cookies) |
page.on('request', ...) |
Обрабатывается через page.route. |
elementHandle.uploadFile(...) |
elementHandle.setInputFiles(...) |
Что надо изменить в скриптах — подробно
Изменить подключение
В Puppeteer первые строки вашего скрипта, скорее всего, выглядели бы примерно так:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
// ...
В Playwright вам не нужно сильно менять код:
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
// ...
Playwright имеет кроссбраузерную поддержку из коробки, и вы можете выбрать, с каким браузером работать, просто изменив первую строку, например const { webkit } = require('playwright');
В Puppeteer это можно было бы сделать с помощью параметров запуска браузера:const browser = await puppeteer.launch({ product: 'firefox' })
browser context
Browser contexts уже поддерживается в Puppeteer:
const browser = await puppeteer.launch();
const context = await browser.createIncognitoBrowserContext();
const page = await context.newPage();
API Playwright передает больше значений в контекст и обрабатывает его по другому:
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
Как и в Puppeteer, для базовых случаев и одностраничных потоков вы можете использовать контекст по умолчанию:
const browser = await chromium.launch();
const page = await browser.newPage();
Если есть сомнения, явно создайте новый контекст в начале вашего скрипта.
Ожидания
Механизм автоматического ожидания в Playwright это означает, что вам, не придется беспокоиться о явном ожидании. Тем не менее поскольку ожидание является одним из самых сложных моментов в автоматизации, вы захотите узнать о различных способах явного ожидания сценария выполнения одного или нескольких условий.
Playwright вносит несколько изменений, о которых следует помнить:
page.waitForNavigation
иpage.waitForSelector
оставляем, но во многих случаях в них нет необходимости из-за умного ожиданияpage.waitForEvent,
был добавлен.Puppeteer’s
page.waitForXPath
был включен вpage.waitForSelector
, который автоматически распознает выражения XPath.page.waitForFileChooser
был удален(см страницу и наш пример загрузки файла)page.waitForNetworkIdle
был объединен сpage.waitForLoadState
(см. состояние networkidle, чтобы воссоздать предыдущее поведение)Был добавлен
page.waitForUrl
, позволяющий дождаться, пока URL-адрес будет загружен с основным фреймом страницы.page.waitFor(timeout)
становитсяpage.waitForTimeout(timeout)
Напоминаем, что
page.waitForTimeout
никогда не должны использоваться в основных сценариях! Жесткие ожидания /спящие режимы следует использовать только в целях отладки.
Viewport
Puppeteer’s page.setViewport
становится page.setViewportSize
в Playwright.
Ввод текста
В то время как у puppeteer
page.type, он же доступен в Playwright и по-прежнему обрабатывает события с клавиатуры, Playwright добавляет page.fill специально для заполнения и очистки форм.
Cookies
Старое:
page.cookies([...urls])
page.deleteCookie(...cookies)
page.setCookie(...cookies)
Новое:
browserContext.cookies([urls])
browserContext.clearCookies()
browserContext.addCookies(cookies)
Обратите внимание на небольшие различия в методах и способах передачи файлов cookie.
XPath selectors
XPath selectors начинаются с (//
или ..
) Playwright автоматически их распознает, тогда как у Puppeteer были специальные методы для них. Это означает, что вам надо написать page.$(xpath_selector)
вместо page.$x(xpath_selector)
, и page.waitForSelector(xpath_selector)
вместо page.waitForXPath(xpath_selector)
. То же самое дляpage.click
и page.fill
.
Эмуляция устройства
Настройки эмуляции устройства в Playwright устанавливаются на уровне Browser Context, например:
const pixel2 = devices['Pixel 2'];
const context = await browser.newContext({ ...pixel2,});
Кроме того, вам также доступны permission для сайта, геолокация и другие параметры.
Скачать файл
Попытка скачать файлы в Puppeteer в headles режиме может быть сложной задачей. Playwright делает это более простым:
const [download] = await Promise.all([
page.waitForEvent('download'),
page.click('#orders > ul > li:nth-child(1) > a')
]);
const path = await download.path();
Загрузить файл
Puppeteer’s elementHandle.uploadFile
становится elementHandle.setInputFiles
.
Смотрите наш пример загрузки файлов.
Request interception
Перехват запросов в Puppeteer осуществляется через page.on('request', ...)
:
await page.setRequestInterception(true)
page.on('request', (request) => {
if (request.resourceType() === 'image') request.abort()
else request.continue()
})
В Playwright, page.route
ищет совпадение URL-адресом по определенному шаблону:
await page.route('**/*', (route) => {
return route.request().resourceType() === 'image'
? route.abort()
: route.continue()
})
Дополнительно по этой теме смотрите подробный разбор по перехвату запросов
Для многих пунктов в списке выше существуют варианты одной и той же функции на уровне
Page
,Frame
andElementHandle
level. Для простоты мы сообщили только об одном.
Новые возможности, о которых нужно знать
При переходе от Puppeteer к Playwright убедитесь, что вы знаете о многих новых функциях, которые предлагает Playwright, они помогут открыть новые решения и возможности для вашего тестирования или мониторинга.
Новые селекторы
Playwright обеспечивает гибкость при обращении к элементам пользовательского интерфейса через селекторы, открывая другие механизмы выбора. Помимо CSS и XPath, команда Playwright добавляет:
Playwright специфичный селектор:
:nth-match(:text("Buy"), 3)
Селектор по тексту.:
text=Add to Cart
Связанные селекторы:
css=preview >> text=In stock
Вы можете создать свой селектор
Подробнее как использовать селекторы смотрите в нашем полном разбор.
Сохранение и восстановления состояния
Playwright позволяет сохранять состояние авторизации (файлы cookie и localStorage) данного сеанса и повторно использовать его для следующих запусков тестов.
Повторное использование состояния поможет сэкономить время в тестах, пропуская этап авторизации, где это не предполагается проверять
Locator API
Вас заинтересует API-интерфейс Playwright Locator, это позволяет инкапсулировать логику, необходимую для извлечения элемента, позволяя легко извлекать обновленный элемент DOM в различные моменты времени в вашем тесте. Это будет полезно, если вы структурируете свои тесты в соответствии с Page Object Model, или если вам интересно это попробовать
Playwright Inspector
Playwright Inspector — это инструмент с графическим интерфейсом, который удобен при отладке сценариев, позволяя пошагово выполнять инструкции по сценарию, или найти причину сбоя.
Inspector также пригодится благодаря своей способности предлагать селекторы для элементов страницы и даже записывать новые сценарии с нуля.
Playwright test runner
Playwright включает в себя, Playwright Test, который добавляет полезные функции для e2e тестирования, такие как распараллеливание прямо из коробки, средства тестирования, хуки и многое другое.
Trace Viewer
Playwright Trace Viewer позволяет исследовать trace, записанные с помощью Playwright Test или BrowserContext Tracing API. Трассировки — это то место, где вы можете получить наиболее детальное представление о выполнении вашего скрипта.
Генератор тестов
Вы можете использовать Playwright Test Generator для записи взаимодействий в вашем браузере. Результатом будет полноценный скрипт, готовый к просмотру и выполнению.