Nunca uses waitForTimeout — espera la red real
Elimina hoy mismo cada timeout fijo de tu suite de tests. Un waitForTimeout(5000) es una adivinanza: cuando la app responde en 300 ms desperdicia 4.7 segundos en cada ejecución, y cuando el CI está lento igual falla. Las esperas fijas son la única técnica que hace una suite más lenta y más frágil al mismo tiempo — y ambos problemas desaparecen en cuanto esperas la condición real en lugar del reloj.
Por qué una espera fija nunca puede estar bien
No existe un número correcto para un sleep. Si lo eliges corto, el test falla en un runner de CI cargado; si lo eliges largo, pagas la demora completa en cada ejecución verde. Multiplica un sleep de 5 segundos por 40 tests y 20 corridas de CI al día, y estás quemando más de una hora diaria de máquina en esperas que no verifican nada.
Los test runners modernos coinciden. La guía oficial de Playwright recomienda las aserciones web-first: "By using web first assertions Playwright will wait until the expected condition is met." Cypress lista "waiting for arbitrary time periods using cy.wait(Number)" como un anti-patrón explícito y recomienda "use route aliases or assertions to guard Cypress from proceeding until an explicit condition is met."
Qué esperar en su lugar
1. La respuesta de red. Si la UI está esperando un request, el test también debería:
// Playwright — wait for the exact request the click triggers
const responsePromise = page.waitForResponse(
(res) => res.url().includes('/api/users') && res.status() === 200
);
await page.getByTestId('fetch-users').click();
await responsePromise;
// Cypress — alias the route, then wait on the alias
cy.intercept('GET', '/users').as('getUsers');
cy.get('[data-testid="fetch-users"]').click();
cy.wait('@getUsers');
2. El resultado visible. Las aserciones web-first vuelven a revisar el DOM "over and over, until the condition is met or until the timeout is reached" — con un timeout por defecto de 5 segundos en Playwright:
await expect(page.getByTestId('status')).toHaveText('Submitted');
await expect(page.getByRole('row')).toHaveCount(2);
Ambas continúan en el instante en que la condición se cumple. App rápida, test rápido; red lenta, test paciente. El mismo código.
Reglas prácticas
| Escribiste un sleep porque… | Reemplázalo con |
|---|---|
| Los datos siguen cargando | waitForResponse / cy.wait('@route') con alias |
| El elemento aún no aparece | expect(locator).toBeVisible() — reintenta solo |
| El texto no se actualizó | expect(locator).toHaveText(...) |
| Una animación está terminando | Asevera sobre el estado final, no la transición |
| "Solo necesita un momento" | Aún no conoces la condición — encuéntrala primero |
Las acciones de Playwright además auto-esperan por sí solas: click() ejecuta chequeos de accionabilidad (visible, habilitado, estable) antes de disparar, así que la mayoría de los sleeps previos a un click nunca fueron necesarios.
Trucos avanzados
- Prohíbe los sleeps mecánicamente. Agrega una regla de lint o un grep al CI: falla el build ante
waitForTimeout(ycy.wait(seguido de un número. Una regla vale más que un recordatorio en code review. - Haz polling de lo que sea. ¿No hay locator para tu condición?
expect.poll(...)yexpect(...).toPass()de Playwright reintentan una función arbitraria — un endpoint de estado, una fila de base de datos — con la misma semántica de reintentos. - Ajusta timeouts globalmente, no localmente. Si el CI es realmente más lento, sube el timeout de aserciones en una línea de configuración en lugar de regar sleeps por test.
- Díselo a tu agente de IA. Los agentes de código copian
waitForTimeoutde tests viejos sin dudar. Una línea en las instrucciones del proyecto — "nunca uses timeouts fijos en tests; espera respuestas o aserciones" — mantiene limpios los tests generados desde el origen.
Recursos
- Playwright — Best practices: use web-first assertions
- Playwright — Auto-retrying assertions
- Playwright — API de
page.waitForResponse() - Playwright — Auto-waiting y chequeos de accionabilidad
- Cypress — Best practices: unnecessary waiting
¿Desarrollas código asistido por IA? Yeda AI diseña, audita y entrega sistemas LLM de producción.