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