De MFTF a Playwright para tests E2E en Magento 2

Las ventajas de los tests E2E modernos en TypeScript frente al viejo método de XML y Selenium


Durante años mis tests de extremo a extremo (E2E) en Magento 2 estaban escritos en MFTF, el Magento Functional Testing Framework. Viene con la plataforma y cumple, pero cada test significaba escribir XML movido por Selenium por debajo: verboso, lento y difícil de depurar. Hace un tiempo trasladé ese trabajo a Playwright como alternativa a MFTF, y no pienso volver atrás. Esto es lo que cambió de verdad, característica por característica.

La forma antigua frente a la nueva

MFTF

la forma tradicional

  • Tests escritos en XML
  • Repartidos en muchos ficheros
  • Selenium: más lento y frágil
  • Depuras desde una captura
  • Acoplado al core de Magento

Playwright

la forma moderna

  • Tests escritos en TypeScript
  • Un único fichero legible
  • Auto-espera y en paralelo
  • Depuras con el trace viewer
  • Una dependencia independiente

El mismo objetivo — «¿sigue funcionando el checkout?» — por dos caminos muy distintos.

El resto de este artículo son, en realidad, esas filas explicadas.

XML en varios ficheros frente a un único spec de TypeScript

En MFTF un simple test de «añadir al carrito» se reparte entre un fichero de test, un fichero de sección para los selectores y un fichero de datos para el producto — todo XML, todo referenciado entre sí con claves de texto:

xml
<!-- Test/Mftf/Test/AddToCartTest.xml -->
<test name="AddSimpleProductToCartTest">
    <amOnPage url="{{SimpleProduct.urlKey}}.html" stepKey="goToProduct"/>
    <waitForPageLoad stepKey="waitForProductPage"/>
    <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addToCart"/>
    <waitForElementVisible selector="{{StorefrontMessagesSection.success}}" stepKey="waitForSuccess"/>
    <see userInput="You added Simple Product to your shopping cart." stepKey="assertSuccess"/>
</test>

El mismo test en Playwright es un único fichero, y se lee como los pasos que daría una persona:

ts
test('añade un producto al carrito', async ({ page }) => {
  await page.goto('/simple-product.html');
  await page.getByRole('button', { name: 'Add to Cart' }).click();
  await expect(page.getByRole('alert')).toContainText('added');
});

Sin fichero de sección, sin fichero de datos, sin un stepKey en cada línea. Tu editor lo autocompleta, TypeScript detecta las erratas y refactorizar es un rename en vez de un buscar-y-reemplazar por todo el XML.

Esperas manuales frente a auto-espera

Fíjate en lo que falta en la versión de Playwright: los pasos waitForPageLoad y waitForElementVisible. Playwright auto-espera — un clic espera primero a que el elemento sea visible, esté habilitado y estable, y expect(...) reintenta hasta que la aserción pasa o se agota el tiempo. En MFTF (vía Selenium) añades esas esperas a mano, y olvidar una es la causa clásica de un test que pasa en local y falla en CI. La mayor parte de mis fallos intermitentes simplemente desapareció.

Una captura frente al trace viewer

Esto cambió mi forma de depurar. Cuando un test de MFTF falla en CI normalmente obtienes una captura y un stack trace, y te toca adivinar. Playwright graba un trace en el primer reintento — una línea de tiempo completa que abres en local y recorres:

bash
npx playwright show-trace trace.zip

Cada acción, cada petición de red, un snapshot del DOM en cada paso y la consola. En vez de reproducir el fallo, lo ves ocurrir. También hay un modo UI en vivo (--ui) para escribir tests y un generador de código (--codegen) que escribe los selectores por ti.

Lento y secuencial frente a rápido y en paralelo

Playwright ejecuta los tests en paralelo entre procesos de trabajo desde el primer momento, y la automatización del navegador habla directamente con Chromium en lugar de pasar por la pila de Selenium/WebDriver. En las suites que he migrado el tiempo de reloj bajó drásticamente — lo suficiente como para que correr E2E en cada push sea realista en lugar de una tarea nocturna.

Datos de prueba limpios y aislados

Lo único que vale la pena conservar de MFTF son sus data fixtures — nunca asumas que los datos «ya están ahí». Playwright lo hace elegante con las fixtures: cada test siembra exactamente lo que necesita a través de la API REST de Magento, lo usa y lo destruye después, sin esfuerzo por parte de quien escribe el test. Los ejecuto contra un entorno local de Warden que se parece mucho a producción.

1SembrarCrea un cliente + producto vía la API REST de Magento
2EjecutarDatos frescos y aislados; página autenticada
3LimpiarBorra el cliente + producto vía la API REST

Cada test siembra sus propios datos y los destruye — sin estado compartido, sin dejar nada en la base de datos.

En el spec nunca ves la fontanería. Solo pides la fixture:

ts
test('muestra mis pedidos', async ({ authenticatedPage }) => {
  // se creó un cliente nuevo y se inició sesión por ti;
  // se elimina automáticamente cuando el test termina.
  await authenticatedPage.goto('/customer/account/');
  await expect(authenticatedPage.getByRole('heading', { name: 'My Account' })).toBeVisible();
});
Sembrar por la API es maravilloso en local y staging, y peligroso en producción. Merece la pena hacer que tu helper lance un error si se intenta una escritura contra una tienda real — eso convierte un error aterrador en un test que simplemente falla sin consecuencias.

Sin atarse al ciclo de versiones de Magento

Como MFTF viene con la plataforma, su versión se mueve cuando Magento se mueve. Playwright es solo una dependencia de desarrollo de npm que actualizas a tu ritmo, independiente de la versión de Magento de la tienda. Una cosa menos acoplada a la actualización.

Lo único que MFTF sí tiene

Por justicia: MFTF viene con una enorme biblioteca de action groups y secciones de página ya hechas para los flujos del core, y se mantiene estrictamente dentro de las herramientas de Magento. Si eso le importa a tu equipo, sigue siendo una opción defendible. Para el trabajo que hago, nada de eso compensó la velocidad, los specs en TypeScript y el trace viewer de Playwright.

Hacerlo reutilizable

Un paso extra mereció la pena entre proyectos: moví las piezas compartidas — page objects, fixtures, el helper de la API, una configuración base y un workflow de CI — a un único paquete interno que cada tienda instala, de modo que un arreglo en un sitio llega a todas. Esa forma reutilizable está inspirada en el magento2-bdd-e2e-testing-suite de elgentos (MIT) — una estupenda suite de Playwright de código abierto para Magento 2 y Hyvä. Si estás probando una sola tienda y quieres algo ya hecho, empieza por ahí.

Preguntas frecuentes

¿Es Playwright una buena alternativa a MFTF para Magento 2?
Para la mayoría de pruebas de storefront y funcionales, sí. Playwright es más rápido, mucho más fácil de depurar gracias a su trace viewer, y sus tests en TypeScript son menos frágiles que el enfoque de XML y Selenium de MFTF. MFTF sigue teniendo sentido si dependes mucho de sus action groups o necesitas quedarte estrictamente dentro de las herramientas de Magento.
¿Se puede usar Playwright para probar una tienda Magento 2?
Sin duda. Playwright controla un navegador real contra tu storefront de Magento como con cualquier otro sitio, y puedes sembrar y limpiar los datos de prueba a través de la API REST de Magento para que cada test corra aislado. Funciona tanto con temas Luma como Hyvä.
¿Es Playwright más rápido que MFTF?
En mi experiencia, claramente. Playwright ejecuta los tests en paralelo desde el primer momento y habla directamente con Chromium en lugar de pasar por la pila de Selenium/WebDriver, así que el tiempo de reloj en las suites que migré bajó drásticamente — lo suficiente para correr tests E2E en cada push en vez de solo por la noche.
¿Tengo que renunciar a las data fixtures de MFTF?
No — conservas la misma idea. En lugar de las data entities de MFTF, cada test de Playwright crea los clientes o productos que necesita vía la API REST de Magento en una fixture y los borra después, de modo que no queda nada en la base de datos.