Playwright’s getByRole
использует querySelectorAll('*')
и сопоставляет элементы по доступному имени.
Введение
Понимание эффективности различных стратегий локаторов является ключевым в области веб-автоматизации и тестирования с помощью Playwright. В этой статье мы сравним эффективность локатора getByRole с CSS-селекторами, дадим практические рекомендации по выбору наиболее подходящего метода и объясним его технические аспекты.
Подпишитесь на наш ТЕЛЕГРАМ КАНАЛ ПО АВТОМАТИЗАЦИИ ТЕСТИРОВАНИЯ
Мы использовали внутренние CSS-селекторы Page#getByRole в кодовой базе SerpApi. Однако getByRole локатор работал в 1,5 раза медленнее по сравнению со стандартными CSS-селекторами,что вызвало необходимость провести исследование причин этого различия в производительности. Вероятно, это расхождение связано с использованием функции querySelectorAll(‘*’) в Playwright и сопоставление элементов по доступному имени. Разобраться в этом особенно важно разработчикам, которые ставят приоритетом скорость в своих сценариях автоматизации.
Глубокое погружение: как работает getByRole
Функция getByRole в Playwright – не просто метод для поиска веб-элементов, это сложный механизм с несколькими уровнями взаимодействия в архитектуре Playwright. Давайте разберемся в этом процессе на примере. Рассмотрим код:
await page.getByRole('button', { name: 'Enter address manually' }).click();
Команда getByRole
запускает каскад действий в Playwright:
- Page#getByRole создает
локатор
. - Locator#click делегирует вызов
Frame#click
передаваяLocator#_selector
. - Frame#click делегирует вызов
Channel#click
.Frame
наследует_channel
отChannelOwner
.ChannelOwner#_channel
является JS Proxy объектом, основанным наEventEmitter
. - Клиент
Frame
отправляет событие на серверFrame#click
. - FrameSelector#resolveInjectedForSelector внедряет скрипт
FrameExecutionContext#injectedScript
на страницу, управляемую Playwright. КонструкторInjectedScript#constructor
добавляет движок дляgetByRole
локатора. - createRoleEngine вызывает
parseAttributeSelector
иqueryRole
. - queryRole вызывает
querySelectorAll('*')
и сопоставляет элемент.
По сравнению с getByRole
, локатор с обычным CSS-селектором просто обходит DOM и работает в 1,5 раза быстрее.
Производительность
Сравнительные тесты показали, что обычный локатор, использующий CSS-селекторы, превосходит getByRole
в 1,5 раза. Интересно, что метод $.then
оказался в 2 раза медленнее в наших тестах.
console.time("getByRole"); for (let i = 0; i < 100; i++) { const textContent = await page.getByRole('button', { name: 'Enter address manually' }).textContent() } console.timeEnd("getByRole"); console.time("locator"); for (let i = 0; i < 100; i++) { const textContent = await page.locator('.ektjNL').textContent() } console.timeEnd("locator"); console.time("$.then"); for (let i = 0; i < 100; i++) { const textContent = await page.$('.ektjNL').then(e => e.textContent()) } console.timeEnd("$.then"); // Output: // getByRole: 677.5ms // locator: 497.306ms // $.then: 1.135s
Заключение
В веб-автоматизации понимание локаторов Playwright – getByRole
и CSS-селекторов – является ключевым. getByRole
отличается своей ясностью, в то время как CSS-селекторы обеспечивают более высокую скорость выполнения. Это важно в больших тестовых наборах, где каждая секунда имеет значение. Выбирайте с умом: getByRole
для читабельности, CSS-селекторы для повышения эффективности выполнения тестов.
Перевод статьи «Playwright’s getByRole locator is 1.5x slower than CSS selectors».
Пингбэк: Большой учебник по Playwright