---
title: "Sleepy Test"
type: "test-smell"
slug: "sleepy-test"
url: "http://localhost:3000/es/test-smells/sleepy-test.md"
category: "Olores erráticos"
description: "Una Sleepy Test pausa la ejecución con un retardo codificado de forma fija (`Thread.sleep`, `setTimeout`, `cy.wait(2000)`, `page.waitForTimeout`) para esperar a trabajo asíncrono, en lugar de esperar a la condición real."
---
# Sleepy Test

> Una Sleepy Test pausa la ejecución con un retardo codificado de forma fija (`Thread.sleep`, `setTimeout`, `cy.wait(2000)`, `page.waitForTimeout`) para esperar a trabajo asíncrono, en lugar de esperar a la condición real.

## Signs and Symptoms

Ves un retardo con número mágico colocado entre una acción y su aserción, con un comentario disculpándose por ello:

```js
test('order is processed', async () => {
  submitOrder(order);

  // dale tiempo al worker para terminar
  await new Promise((r) => setTimeout(r, 2000));

  expect(await getOrderStatus(order.id)).toBe('processed');
});

```

Señales reveladoras:

* Sleeps fijos en cuerpos de prueba o en hooks: `Thread.sleep(500)`, `await sleep(1000)`, `time.sleep(2)`, `cy.wait(3000)`, `await page.waitForTimeout(2000)`, `browser.pause(2000)`.
* Comentarios como `// wait for the animation`, `// let the DB catch up`, `// flaky without this`.
* La duración del sleep deriva al alza con el tiempo (`1000` se convierte en `2000` y luego en `5000`) a medida que la gente combate fallos intermitentes rellenando el retardo.
* El número es la _única_ sincronización: no hay aserción, sondeo ni evento al que la espera esté realmente vinculada.
* Una suite lenta donde el tiempo de reloj de pared está dominado por sleeps en lugar de por trabajo real.

El olor trata de la espera _incondicional_. `cy.wait('@apiAlias')` o `await expect(locator).toBeVisible()` esperan a una condición y están bien; `cy.wait(2000)` y `page.waitForTimeout(2000)` esperan al reloj y no.

## Reasons for the Problem

**Por qué ocurre**

* Una operación asíncrona (una cola, un temporizador, una animación, una llamada de red, un hilo en segundo plano) no tiene un punto de enganche obvio sobre el que esperar, así que un retardo es el camino de menor resistencia.
* Una prueba fallaba de forma intermitente y alguien la "arregló" insertando o alargando un sleep hasta que se puso en verde en su máquina.
* La prueba interactúa con un sistema externo real (reloj, planificador, sistema de ficheros, servicio HTTP) cuya finalización no es observable, así que se adivina el tiempo.

**Por qué es perjudicial**

* **Fiabilidad / falsa confianza.** Un sleep codifica una suposición: "el trabajo termina en N ms". El tiempo de procesamiento varía entre máquinas, según la carga de CI y entre ejecuciones, así que la prueba es no determinista: pasa en local y falla en un agente de CI cargado o, peor aún, el sleep es _demasiado corto_ y la aserción compite con el código, pasando solo por suerte en el cronometraje. Es una de las causas raíz más citadas de las pruebas inestables (flaky).
* **Lentitud.** Un sleep fijo siempre espera toda la duración, aunque el trabajo terminase en 20 ms. Multiplicado por toda una suite, los sleeps convierten segundos de trabajo real en minutos de espera ociosa, lo que desincentiva ejecutar las pruebas a menudo.
* **Mantenibilidad.** El número mágico es frágil: acelerar o ralentizar el sistema bajo prueba rompe en silencio el contrato de tiempo, y el único "arreglo" al que recurre la gente es subir el número, un trinquete que vuelve la suite más lenta y _aun así_ inestable.
* **Legibilidad.** El retardo oculta _qué_ está esperando realmente la prueba. Un lector no puede saber si `sleep(2000)` protege una escritura en BD, un renderizado o nada en absoluto, así que la intención de la prueba queda oscurecida.

## Treatment

Sustituye "esperar un tiempo fijo" por "esperar a la condición". Identifica la señal observable de que el trabajo asíncrono ha terminado y bloquéate sobre _esa_ con un timeout generoso.

1. **Sondea la condición.** Usa un helper de sondeo/reintento (Awaitility en la JVM, `vi.waitFor` / `waitFor` en Vitest o Testing Library, el `waitFor` de Jest, o las aserciones con reintento automático de tu runner) para que la prueba avance en el instante en que la condición es verdadera y solo falle tras un timeout.
2. **Prefiere las aserciones con espera integradas.** Las herramientas de E2E web ya reintentan: las aserciones web-first de Playwright (`await expect(locator).toBeVisible()`) y los comandos con reintento automático de Cypress eliminan por completo la necesidad de esperar.
3. **Espera a eventos, no al reloj.** Aguarda la promesa, haz `await` de la respuesta de red, o usa un `CountDownLatch`/callback/`waitFor('@alias')` que el código de producción señalice de verdad.
4. **Controla el tiempo en lugar de gastarlo.** Cuando el retardo es un temporizador real del código bajo prueba, usa temporizadores falsos (`jest.useFakeTimers()`, `vi.useFakeTimers()`, `vi.advanceTimersByTimeAsync`) para avanzar el reloj de forma determinista en vez de dormir.

Antes:

```js
test('order is processed', async () => {
  submitOrder(order);
  await new Promise((r) => setTimeout(r, 2000)); // sleepy
  expect(await getOrderStatus(order.id)).toBe('processed');
});

```

Después (sondea la condición con un timeout acotado):

```js
import { vi } from 'vitest';

test('order is processed', async () => {
  submitOrder(order);
  await vi.waitFor(
    async () => expect(await getOrderStatus(order.id)).toBe('processed'),
    { timeout: 5000, interval: 50 },
  );
});

```

Equivalentes en Playwright/Cypress:

```js
// Playwright: la aserción web-first reintenta automáticamente hasta que sea visible o expire el timeout
await expect(page.getByText('processed')).toBeVisible();

// Cypress: espera a la petición, no a un número
cy.intercept('POST', '/orders').as('createOrder');
cy.wait('@createOrder');

```

El resultado no espera más de lo necesario, falla rápido con un mensaje de timeout claro y ya no depende de la velocidad de la máquina.

## Detected by

- **sonar** `java:S2925` — "Thread.sleep" should not be used in tests (https://rules.sonarsource.com/java/RSPEC-2925/)
- **eslint-plugin-playwright** `playwright/no-wait-for-timeout` — no-wait-for-timeout (disallow page.waitForTimeout) (https://github.com/playwright-community/eslint-plugin-playwright/blob/main/docs/rules/no-wait-for-timeout.md)
- **eslint-plugin-cypress** `cypress/no-unnecessary-waiting` — no-unnecessary-waiting (disallow cy.wait with a number) (https://github.com/cypress-io/eslint-plugin-cypress/blob/master/docs/rules/no-unnecessary-waiting.md)
- **eslint-plugin-ui-testing** `ui-testing/no-hard-wait` — no-hard-wait (cy.wait, page.waitForTimeout, browser.pause, t.wait) (https://github.com/kwoding/eslint-plugin-ui-testing/blob/master/docs/rules/no-hard-wait.md)
