• Mar 17, 2026

Locators en Playwright: por qué ya no vas a extrañar a Selenium (o sí, pero solo un poco)

Playwright tiene una forma de localizar elementos que cambia bastante las reglas del juego. Veamos por qué.

Si venís del mundo de Selenium (y siendo parte de la comunidad de Free Range Testers, hay bastantes chances de que así sea) probablemente ya tengas una relación de amor/odio con los locators. Por un lado, lograste dominar XPath como si fuera tu idioma nativo. Por el otro, más de una vez quisiste tirar la computadora cuando un test que funcionaba perfecto empezó a fallar sin que nadie tocara nada... solo porque el dev movió un <div>.

Buenas noticias: Playwright tiene una forma de localizar elementos que cambia bastante las reglas del juego. Veamos por qué.

Primero, un repaso de cómo localiza elementos Selenium

En Selenium, para interactuar con un elemento web necesitás identificarlo usando la clase By, que te da varias estrategias: By.ID, By.NAME, By.CLASS_NAME, By.CSS_SELECTOR, By.XPATH, entre otras.

En Java, se ve algo así:

WebDriver driver = new ChromeDriver();
driver.get("<https://ejemplo.com>");

// Por ID
WebElement boton = driver.findElement(By.id("submit-btn"));

// Por XPath
WebElement campo = driver.findElement(By.xpath("//input[@name='username']"));

// Por CSS
WebElement titulo = driver.findElement(By.cssSelector("h1.main-title"));

Y en Python:

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("<https://ejemplo.com>")

# Por ID
boton = driver.find_element(By.ID, "submit-btn")

# Por XPath
campo = driver.find_element(By.XPATH, "//input[@name='username']")

# Por CSS
titulo = driver.find_element(By.CSS_SELECTOR, "h1.main-title")

El problema no está tanto en la sintaxis sino en lo que pasa después: ¿el elemento está visible? ¿Ya cargó? ¿Está habilitado? Selenium, por defecto, no se hace cargo de esas preguntas. Vos sí. Y ahí empiezan los Thread.sleep(), los WebDriverWait y el festival de TimeoutException a las 2 de la mañana.

Ahora hablemos de Playwright

Playwright toma un camino completamente distinto. En lugar de darte una lista de estrategias intercambiables, te propone locators semánticos que piensan como lo haría un usuario (o como lo haría un test de accesibilidad bien escrito).

getByRole

Este es el que Playwright te va a recomendar en casi todos los casos. Localiza elementos según su rol ARIA, que es justamente cómo los navegadores y las tecnologías de asistencia ven la página.

await page.getByRole('button', { name: 'Enviar' }).click();
await page.getByRole('textbox', { name: 'Usuario' }).fill('agustina');
await page.getByRole('heading', { name: 'Bienvenida' }).isVisible();

¿Por qué esto es más robusto? Porque si el dev cambia el id del botón o mueve el elemento en el DOM, el test sigue funcionando siempre y cuando el botón siga siendo un botón con el texto "Enviar". Estás testeando comportamiento, no implementación.

getByText

Para cuando necesitás encontrar un elemento por su contenido de texto visible.

await page.getByText('¿Olvidaste tu contraseña?').click();

getByLabel

Perfecto para formularios. Busca inputs asociados a una <label>.

await page.getByLabel('Correo electrónico').fill('agustina@ejemplo.com');

getByPlaceholder

Para inputs que tienen un placeholder pero no una label visible.

await page.getByPlaceholder('Buscá un producto...').fill('zapatillas');

getByTestId

Cuando el equipo de desarrollo agrega atributos data-testid específicos para testing.

await page.getByTestId('checkout-button').click();

getByAltText y getByTitle

Para imágenes y elementos con atributo title.

await page.getByAltText('Logo de la empresa').isVisible();

La comparativa que estabas esperando

Escenario 1: hacer login

Selenium (Java)

driver.findElement(By.id("username")).sendKeys("agustina");
driver.findElement(By.id("password")).sendKeys("1234");
driver.findElement(By.cssSelector("button[type='submit']")).click();

Playwright (TypeScript)

await page.getByLabel('Usuario').fill('agustina');
await page.getByLabel('Contraseña').fill('1234');
await page.getByRole('button', { name: 'Ingresar' }).click();

La versión de Playwright describe qué hace el usuario, no qué atributo tiene el elemento. Es más fácil de leer, de mantener y de entender cuando falla.


Escenario 2: verificar un mensaje de error

Selenium (Python)

mensaje = driver.find_element(By.XPATH, "//div[@class='error-message' and contains(text(),'Usuario incorrecto')]")
assert mensaje.is_displayed()

Playwright (TypeScript)

await expect(page.getByText('Usuario incorrecto')).toBeVisible();

Menos código. Sin XPath. Y encima Playwright va a reintentar automáticamente esta assertion hasta que el elemento aparezca o hasta que se acabe el timeout. No necesitás escribir un wait explícito.


Escenario 3: trabajar con un menú desplegable

Selenium (Java)

WebElement dropdown = driver.findElement(By.id("categoria"));
Select select = new Select(dropdown);
select.selectByVisibleText("Electrónica");

Playwright (TypeScript)

await page.getByLabel('Categoría').selectOption('Electrónica');

¿Y si igual necesito CSS o XPath en Playwright?

Totalmente válido. Playwright también los soporta para casos donde los locators semánticos no alcanzan:

// CSS Selector
await page.locator('input.search-box').fill('playwright');

// XPath
await page.locator('//table//tr[2]/td[1]').innerText();

// Combinando locators
await page.getByRole('list').getByRole('listitem').filter({ hasText: 'Destacado' }).click();

Pero la recomendación de Playwright es clara: los locators semánticos primero. El CSS y el XPath quedan para cuando no hay otra.


¿Qué hace a los locators de Playwright más robustos?

Todo se reduce a tres cosas:

Piensan como el usuario. getByRole('button', { name: 'Comprar' }) falla si y solo si ese botón deja de existir o de llamarse "Comprar". No le importa si le cambiaron el id o si alguien le agregó una clase CSS.

El auto-waiting está incorporado. Playwright no intenta interactuar con un elemento hasta que esté visible, habilitado y listo para recibir acciones. En Selenium, eso era tu problema.

Los locators son lazy. Un page.getByRole('button', { name: 'Enviar' }) no busca el elemento en el momento en que se declara, sino cuando se usa. Esto permite encadenarlos, filtrarlos y componerlos sin preocuparte por el orden de carga de la página.


¿Querés aprender más?

Si todo esto te despertó el apetito y querés ir más a fondo, en Free Range Testers tenemos cursos completos para que domines estas herramientas:

Los cursos de Java y Python son independientes entre sí, así que podés elegir el que mejor se adapte a tu stack sin tener que hacer los dos.


La conclusión es bastante clara: Playwright no solo modernizó la forma en que hacemos testing, sino que cambió la filosofía detrás de cómo encontramos los elementos. Menos frágil, más expresivo, más cercano a la experiencia real del usuario. Si todavía no lo probaste, este es un buen momento para arrancar.

Y si ya lo estás usando pero seguís escribiendo XPaths por costumbre... bueno, no te juzgamos. Pero ahora ya no tenés excusas. 😄

Un poco

Sobre mi

Consultor privado e instructor en QA

Más de 16 años en el mercado, trabajando como consultor QA privado para empresas de Nueva Zelanda y Australia en proyectos de gran impacto y siempre a la vanguardia.

Lo que enseño viene de mi experiencia 🧑🏻‍💻

  • Entrega gratuita por correo electrónico

La guía 2025 para conseguir trabajo en Testing de Software

  • Descarga digital
  • 1 archivo

Conseguir trabajo en Testing de Software, en este 2025, presenta desafíos de los que necesitás enterarte YA mismo. En esta guía exclusiva de Free Range Testers vuelco en el tono informal de siempre, mis más de 16 años de experiencia y sobre todo lo relacionado a las nuevas tendencias que van a hacer la gran diferencia a la hora de buscar trabajo. ¡Nos vemos en el libro!

Suscríbete para estar informado de las actividades de Free Range Testers.

0 comments

Sign upor login to leave a comment