---
title: "Sleepy Test"
type: "test-smell"
slug: "sleepy-test"
url: "http://localhost:3000/pt-br/test-smells/sleepy-test.md"
category: "Maus Cheiros Erráticos"
description: "Um Sleepy Test pausa a execução com um atraso fixo no código (`Thread.sleep`, `setTimeout`, `cy.wait(2000)`, `page.waitForTimeout`) para esperar por um trabalho assíncrono em vez de esperar pela condição real."
---
# Sleepy Test

> Um Sleepy Test pausa a execução com um atraso fixo no código (`Thread.sleep`, `setTimeout`, `cy.wait(2000)`, `page.waitForTimeout`) para esperar por um trabalho assíncrono em vez de esperar pela condição real.

## Signs and Symptoms

Você vê um atraso com número mágico posicionado entre uma ação e sua asserção, com um comentário se desculpando por ele:

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

  // dá tempo para o worker terminar
  await new Promise((r) => setTimeout(r, 2000));

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

```

Sinais reveladores:

* Sleeps fixos no corpo dos testes ou em hooks: `Thread.sleep(500)`, `await sleep(1000)`, `time.sleep(2)`, `cy.wait(3000)`, `await page.waitForTimeout(2000)`, `browser.pause(2000)`.
* Comentários como `// espera a animação`, `// deixa o banco se atualizar`, `// instável sem isto`.
* A duração do sleep cresce ao longo do tempo (`1000` vira `2000` vira `5000`) à medida que as pessoas combatem falhas intermitentes acolchoando o atraso.
* O número é a _única_ sincronização — não há asserção, polling ou evento ao qual a espera esteja de fato atrelada.
* Uma suíte lenta cujo tempo de relógio é dominado por sleeps em vez de trabalho real.

O smell é sobre espera _incondicional_. `cy.wait('@apiAlias')` ou `await expect(locator).toBeVisible()` esperam por uma condição e estão ok; `cy.wait(2000)` e `page.waitForTimeout(2000)` esperam pelo relógio e não estão.

## Reasons for the Problem

**Por que acontece**

* Uma operação assíncrona (uma fila, um timer, uma animação, uma chamada de rede, uma thread em segundo plano) não tem um gancho óbvio em que esperar, então um atraso é o caminho de menor resistência.
* Um teste estava falhando de forma intermitente e alguém o "consertou" inserindo ou aumentando um sleep até ele ficar verde na máquina dessa pessoa.
* O teste interage com um sistema externo real (relógio, agendador, sistema de arquivos, serviço HTTP) cuja conclusão não é observável, então o tempo é adivinhado.

**Por que prejudica**

* **Confiabilidade / falsa confiança.** Um sleep codifica uma suposição — "o trabalho termina em N ms." O tempo de processamento varia entre máquinas, carga de CI e execuções, então o teste é não determinístico: passa localmente e falha em um agente de CI sobrecarregado, ou pior, o sleep é _curto demais_ e a asserção corre contra o código, passando apenas por sorte de tempo. Essa é uma das causas-raiz mais citadas de testes instáveis.
* **Lentidão.** Um sleep fixo sempre espera a duração completa, mesmo quando o trabalho terminou em 20 ms. Multiplicados por toda uma suíte, os sleeps transformam segundos de trabalho real em minutos de espera ociosa, o que desestimula rodar os testes com frequência.
* **Manutenibilidade.** O número mágico é frágil: acelerar ou desacelerar o sistema sob teste quebra silenciosamente o contrato de tempo, e a única "correção" à qual as pessoas recorrem é aumentar o número — uma catraca que deixa a suíte mais lenta e _ainda assim_ instável.
* **Legibilidade.** O atraso esconde _o que_ o teste está de fato esperando. Um leitor não consegue dizer se `sleep(2000)` protege uma escrita no banco, uma renderização ou nada, então a intenção do teste fica obscurecida.

## Treatment

Substitua "esperar um tempo fixo" por "esperar pela condição." Identifique o sinal observável de que o trabalho assíncrono terminou e, então, bloqueie _nele_ com um timeout generoso.

1. **Faça polling pela condição.** Use um helper de polling/retry — Awaitility (JVM), `vi.waitFor` / `waitFor` (Vitest, Testing Library), o `waitFor` do Jest ou as asserções com retry automático do seu executor de testes — para que o teste prossiga no instante em que a condição for verdadeira e só falhe após um timeout.
2. **Prefira asserções aguardadas nativas.** Ferramentas de E2E web já fazem retry: as asserções web-first do Playwright (`await expect(locator).toBeVisible()`) e os comandos com retry automático do Cypress eliminam totalmente a necessidade de esperar.
3. **Espere por eventos, não pelo relógio.** Aguarde a promise, faça `await` da resposta de rede, ou use um `CountDownLatch`/callback/`waitFor('@alias')` que o código de produção de fato sinaliza.
4. **Controle o tempo em vez de gastá-lo.** Quando o atraso for um timer real no código sob teste, use fake timers (`jest.useFakeTimers()`, `vi.useFakeTimers()`, `vi.advanceTimersByTimeAsync`) para avançar o relógio de forma determinística em 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');
});

```

Depois (faça polling pela condição com um timeout limitado):

```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 em Playwright/Cypress:

```js
// Playwright — a asserção web-first faz retry automático até ficar visível ou estourar o timeout
await expect(page.getByText('processed')).toBeVisible();

// Cypress — espere pela requisição, não por um número
cy.intercept('POST', '/orders').as('createOrder');
cy.wait('@createOrder');

```

O resultado não espera mais do que o necessário, falha rapidamente com uma mensagem de timeout clara e não depende mais da velocidade da máquina.

## Detected by

- **sonar** `java:S2925` — "Thread.sleep" não deve ser usado em testes (https://rules.sonarsource.com/java/RSPEC-2925/)
- **eslint-plugin-playwright** `playwright/no-wait-for-timeout` — no-wait-for-timeout (proíbe 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 (proíbe cy.wait com um número) (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)
