Tests E2E con IA: el agente navega, el código verifica
Tests E2E con IA usando e2e de Tester Army: el agente navega donde el locator es frágil, el replay evita el modelo y la verificación sigue siendo código.

El viernes a las seis alguien renombra un data-testid en el botón de pagar. Nadie toca la lógica. El lunes la pipeline está en rojo: catorce tests E2E fallan por un atributo que ningún usuario ve.
Así que pruebas lo contrario. Montas tests E2E con IA: le das el navegador a un agente y le pides "compra el teclado". Da verde. Y el pedido nunca se creó: el agente vio un spinner, lo interpretó como éxito y siguió.
Entre esos dos fallos está la pregunta. Si dejas que el modelo decida también si el test pasa, has cambiado un test frágil por uno que no sabes si miente.
En corto: en los tests E2E con IA el agente solo debería actuar donde el locator es frágil; la verificación tiene que seguir siendo código determinista. El framework open source e2e de Tester Army está diseñado así: graba los pasos del agente que una aserción posterior confirma y los reproduce sin llamar al modelo hasta que la app cambia. Lo crítico va con expect, no con agent.assert.
¿Qué son los tests E2E con IA?
Un test E2E con IA es un test de extremo a extremo en el que un modelo de lenguaje decide las acciones (clics, formularios, navegación) a partir de un objetivo en lenguaje natural, en lugar de seguir una secuencia fija de selectores.
La diferencia con Playwright clásico es dónde vive el conocimiento de la interfaz. En un script, en tus locators. Con un agente, en el modelo, que lee el árbol de accesibilidad en cada ejecución.
Eso resuelve la fragilidad y abre dos problemas: coste y no determinismo.
Cómo funciona e2e de Tester Army: intención, grabación y replay
e2e combina pasos de agente (agent.act), aserciones semánticas y locators deterministas, y reproduce sin modelo los pasos del agente que una comprobación posterior confirmó.
e2e es el framework open source (Apache-2.0) de Tester Army. A 15 de octubre de 2026 tiene unas 10.700 estrellas en GitHub y va por la versión 0.21.1. El README avisa: está en desarrollo hacia 1.0 y la API y la config pueden cambiar entre versiones menores.
Un test mezcla tres tipos de paso, según la documentación de conceptos:
| Paso | API | ¿Llama al modelo? |
|---|---|---|
| Objetivo | agent.act() |
Sí, salvo que la caché lo reproduzca |
| Aserción semántica | agent.assert(), agent.waitFor(), agent.extract() |
Sí, nunca desde caché |
| Locator | screen + expect |
No |
La clave está en la primera fila. Según la doc de caché, cuando un agent.act() va seguido de una comprobación que pasa, el runner guarda sus acciones en .e2e/cache/. En la siguiente ejecución las repite localizando cada control por rol, nombre y test id (los mismos locators que enseño en el curso de Testing en Angular con Jest y Testing Library), y comprueba que la pantalla acaba igual. Si cuadra, termina sin modelo. Si la UI cambió, el agente retoma desde la pantalla actual.
Fíjate en la condición: solo se graba lo que algo verificó después. Un act sin comprobación detrás queda como unconfirmed. Sin verificación no hay replay: el framework te empuja a escribirla.
Y un test sin pasos de agente no necesita modelo. Puedes empezar con locators puros y meter agent.act() solo donde duele.
Tutorial: tu primer test E2E con IA con npx e2e init
Necesitas Node.js 24.8 o superior (22.22.3 en la rama 22). En Windows, dentro de WSL. En el directorio de tu app:
npx e2e init
El asistente pregunta motor (Web con Playwright o Mobile para iOS/Android) y proveedor de modelo: una suscripción, una API key o un modelo local. Hay opción None para tests sin IA. Escribe e2e.config.ts y un test de ejemplo que no llama al modelo.
Ahora un checkout de tienda. Es un ejemplo del patrón, no un proyecto real:
// tests/checkout.e2e.ts
import { test } from 39;@e2e-dev/web39;;
import { expect } from 39;e2e39;;
test(39;un cliente compra con la tarjeta de prueba39;, async ({ app, agent, screen, browser }) => {
await app.open(39;/products/teclado-mecanico39;);
// AGENTE: variantes, drawer del carrito, banners... la parte frágil
await agent.act(39;add the keyboard to the cart39;);
await expect(screen.getByRole(39;status39;)).toHaveText(39;1 item39;);
// AGENTE: formulario de pago que UX cambia cada sprint
await agent.act(39;complete checkout with the test card {card}39;, {
params: { card: 39;4242 4242 4242 424239; },
});
// DETERMINISTA: lo que el negocio necesita que sea verdad
await expect(browser).toHaveURL(39;/checkout/confirmation39;);
await expect(screen.getByRole(39;heading39;, 39;Order confirmed39;)).toBeVisible();
await expect(screen.getByTestId(39;order-total39;)).toHaveText(39;89,00 €39;);
// SEMÁNTICO: lo que no merece un locator
await agent.assert(39;the page shows an estimated delivery date39;);
});
npx e2e run tests/checkout.e2e.ts
El agente navega donde más cambia el DOM. Cada act es un objetivo atómico seguido de un expect, como pide la doc, para que el replay lo grabe. URL, título y total los comprueba código.
Es el enfoque contrario al de agentes que diagnostican tests de Playwright ya escritos. Allí el script es la fuente de verdad y la IA interviene cuando se rompe. Aquí la intención es la fuente de verdad y el script es una grabación desechable. Coinciden en lo importante: la IA no toca los asserts.
La trampa: agent.assert no es un assert
agent.assert() se lee como una aserción, pero un modelo recibe la frase y un snapshot de texto de la pantalla y emite un veredicto. Puede fallar con ASSERTION_FAILED o con ASSERTION_INCONCLUSIVE si no tiene evidencia. Y nunca se reproduce desde caché: es una llamada al modelo en cada ejecución.
Mi regla: si un bug en esa línea te cuesta dinero o un ticket de soporte, va con expect. Total, estado del pedido, URL, mensaje de error. agent.assert queda para lo difuso: que un texto generado tenga sentido, que un gráfico suba (vision: true).
La propia doc lo dice: cuando el texto exacto importa, usa un locator.
Playwright vs e2e vs Tester Army: comparativa de tests E2E con IA
| Playwright puro | e2e (open source) | Tester Army (SaaS) | |
|---|---|---|---|
| Cómo escribes el test | Código con locators | Locators + agent.act() |
Lenguaje natural, sin código |
| Coste por ejecución | Solo infra | Modelo en la primera pasada y al cambiar la UI (en CI, solo si commiteas .e2e/cache/); asserts semánticos siempre |
Por runs: 99 $/mes (250) o 299 $/mes (1.000); 5 runs gratis |
| Determinismo | Total | Total en expect y replay; agent.assert no |
Depende del agente |
| Auth, OTP, infra | Tú | Tú (los Secret no llegan al modelo) |
Incluido: cuentas de test, OAuth, OTP |
| Dónde corre | Tu CI | Tu CI + tu proveedor de modelo | Su nube |
| Límite o riesgo | Selectores frágiles | Pre-1.0, telemetría activa por defecto | Dependes de un tercero; cifras de clientes autodeclaradas |
Sobre esa última celda: según Tester Army, Novu redujo a la mitad sus tests flaky y Juno pasó de 501 a 791 PRs mergeadas en un mes. Son casos de sus propios clientes. Señal, no benchmark.
Lo que se discute en Hacker News
En el Launch HN de TesterArmy (junio de 2026) un usuario lo planteó así: "E2E tests are now quick to write due to LLMs, and are then deterministic AND cheap to run". Y preguntaba cuánto cuesta en tokens tener un agente en cada test.
Otro preguntó directamente si cacheaban los pasos para no llamar al LLM en ejecuciones posteriores. El fundador respondió que cacheaban la trayectoria del agente, pero todavía no el test completo: querían al agente en el bucle, más como un QA manual que como un script.
El replay sin modelo de e2e es la respuesta a esa objeción, y es el argumento del Show HN de e2e de octubre. Aun así, un comentario pregunta por qué no usar Gherkin con Cucumber y que un agente escriba las step definitions.
Cuándo NO usar tests E2E con IA
Si necesitas una API estable. e2e está antes de 1.0. Una actualización puede cambiar las claves de la caché y obligarte a regrabar.
Si tu CI va cargado. El issue #1144 documenta que la espera del estado final se fija al grabar: un paso grabado en una máquina tranquila puede fallar con REPLAY_STALE bajo --strict-cache al reproducirse con varios workers, aunque el estado acabe apareciendo. Hay un PR con el arreglo, el #1154, sin mergear a 15 de octubre.
Si no controlas el coste en CI. e2e init mete .e2e/cache/ en el .gitignore y en CI la caché es de solo lectura: si no commiteas las grabaciones, cada pipeline arranca sin caché y paga modelo en cada act. Y si las commiteas, una grabación que deja de reproducirse no falla: el agente toma el paso y cada CI paga hasta que alguien la regraba. Usa --strict-cache en CI para enterarte.
Si tus datos no pueden salir. El modelo ve el árbol de accesibilidad y capturas enmascaradas. La doc de seguridad avisa de lo que puede filtrarse: vídeos, command.log y valores no declarados como secreto. Con datos reales, modelo local o nada de agente.
Si no has revisado la telemetría. El CLI envía uso anónimo por defecto, sin contenido de tests ni credenciales. Se desactiva con npx e2e telemetry disable o E2E_TELEMETRY_DISABLED=1.
Por dónde empezar con tests E2E con IA
Coge el test que más se rompe de tu suite. No el más importante: el más frágil. Sustituye solo la navegación que falla por un agent.act() y deja todos los expect como estaban. La guía de migración desde Playwright explica cómo convivir con tu suite archivo a archivo. Si en la segunda ejecución el replay pasa sin llamar al modelo, commitea .e2e/cache/ para que CI también lo reproduzca. Ahí has ganado.
Si te preocupa qué verificar cuando el código lo escribe un agente, es el tema del workshop SDD + Agentic Engineering y de cómo verificar código generado por IA sin leerlo todo.
Si tu app usa agentes en el navegador en producción, lee también por qué los agentes de IA en el navegador se rompen.
Preguntas frecuentes
¿Qué diferencia hay entre agent.act y agent.assert?
agent.act ejecuta un objetivo, y sus acciones se reproducen sin modelo si una comprobación posterior pasó. agent.assert juzga la pantalla con un modelo en cada ejecución. El primero ahorra mantenimiento; el segundo añade coste y no determinismo.
¿Los tests E2E con IA necesitan un modelo en cada ejecución?
No en e2e. Los pasos act verificados se reproducen desde la caché mientras la app no cambie (en CI, solo si commiteas la carpeta .e2e/cache/), y los tests sin pasos de agente no usan modelo. Las aserciones semánticas sí lo llaman siempre.
¿e2e sustituye a Playwright?
No. Su motor web, @e2e-dev/web, usa Playwright con Chromium, Firefox y WebKit. Añade encima objetivos en lenguaje natural, caché de replay y aserciones semánticas.
¿Puedo usar e2e con un modelo local?
Sí. Admite suscripciones, API keys vía AI SDK y endpoints compatibles con OpenAI, incluidos servidores locales. Es la opción si no quieres que el árbol de accesibilidad salga hacia un proveedor externo.
¿Qué es Tester Army y en qué se diferencia de e2e?
Tester Army es la plataforma SaaS: tests en lenguaje natural sin código, cuentas de test con OAuth y OTP, ejecución en PRs y por calendario, alertas en Slack y MCP para Claude Code, Codex y Cursor. e2e es el framework open source que corre en tu repo.
Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.
¿Quieres construir con agentes en serio?
Curso «Construye con IA» con Claude Code, de la idea al producto.
Developer con más de 15 años en frontend y creador de Dominicode. Escribe sobre IA aplicada al desarrollo de software.
¿Te resultó útil este artículo?
Compártelo con tu comunidad y ayuda a otros desarrolladores.