Playwright’s getByRole is 1.5x slower than CSS selectors

Introduction

In the realm of web automation and testing with Playwright, understanding the performance of various locator strategies is key. This article delves into the getByRole locator's efficiency compared to CSS selectors, offering insights into the technical workings and practical implications of these choices.

I wanted to use Page#getByRole's underlying CSS selectors in our codebase. But the getByRole locator was 1.5 times slower compared to the standard CSS selectors, prompting an investigation into the root cause. This performance discrepancy, likely stemming from Playwright’s use of querySelectorAll('*') and matching elements by the accessible name, raises essential considerations for developers prioritizing speed in their automation scripts.

Deep Dive: How getByRole Works

The getByRole function in Playwright is more than just a method to locate web elements; it's a complex mechanism with multiple layers of interaction within the Playwright architecture. Let's demystify this process with an example. Consider this code:

await page.getByRole('button', { name: 'Enter address manually' }).click();

This command sets off a cascade of actions within Playwright:

Compared to the getByRole, the locator with the regular CSS selector just traverses DOM and is 1.5 times faster.

Performance

Comparative tests reveal that a regular locator using CSS selectors outperforms getByRole by 1.5 times. Interestingly, the $.then method trailed, being 2x slower in our tests.

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

Conclusion

In web automation, understanding Playwright's locators — getByRole and CSS selectors — is key. getByRole excels in clarity, while CSS selectors win in speed. Choose wisely: getByRole for testing accessibility and/or user-facing attributes of elements, CSS selectors for efficiency.