← Voltar para artigos
Sincronização

Esperar tempo ou esperar estado?

Como substituir sleeps por condições observáveis, assertions e polling para construir testes mais determinísticos com Playwright.

O problema dos waits fixos

Uma instrução como waitForTimeout(3000) parece resolver problemas de sincronização porque introduz uma pausa previsível no teste. O problema é que a aplicação não possui a mesma velocidade em todas as execuções.

Se o estado esperado chegar em 500 ms, o teste desperdiça 2,5 segundos. Se chegar em 3,2 segundos, o teste falha mesmo tendo recebido quase todo o tempo necessário. O valor escolhido não representa uma condição do sistema; representa apenas uma estimativa.

Espere aquilo que realmente importa

No Playwright, assertions e locators já possuem mecanismos de espera. Em vez de pausar e depois verificar, descreva diretamente a condição que precisa ser satisfeita:

await expect(page.getByText('Pedido pronto')).toBeVisible();

A intenção fica explícita: o teste continua quando “Pedido pronto” estiver visível, dentro do limite configurado.

Quando o estado é numérico

O cenário de Progress Bar do laboratório é um exemplo mais interessante. O teste precisa observar um valor que muda ao longo do tempo, interromper o progresso e depois aguardar 100%.

Nesse tipo de situação, polling permite consultar o estado repetidamente sem definir uma pausa arbitrária entre etapas:

await expect.poll(async () => {
  const value = await progressBar.getAttribute('aria-valuenow');
  return Number(value);
}).toBe(100);

O timeout continua existindo como limite de segurança. Isso é diferente de usá-lo como mecanismo de sincronização. O teste não espera todo o limite: ele termina a espera assim que a condição é atendida.

Eventos também são estados observáveis

Quando uma ação dispara uma nova aba, download ou outro evento, a sincronização deve começar antes da ação para evitar uma corrida:

const [popup] = await Promise.all([
  page.waitForEvent('popup'),
  page.locator('#tabButton').click(),
]);

O teste registra primeiro o evento que espera e executa a ação no mesmo bloco. Isso reduz o risco de o evento acontecer antes de a espera estar ativa.

Uma regra prática

Antes de adicionar um sleep, pergunte: qual mudança observável indica que a aplicação está pronta para o próximo passo? Visibilidade, atributo, texto, resposta de rede, URL, evento ou valor são respostas melhores do que “dois segundos”.

Timeout não é o inimigo

Eliminar waits fixos não significa executar sem timeouts. Um teste precisa de limites para não aguardar indefinidamente. A diferença está no papel de cada mecanismo:

  • wait fixo: define quanto tempo o teste deve obrigatoriamente ficar parado;
  • timeout: define por quanto tempo uma condição pode ser aguardada antes de ser considerada falha;
  • assertion/polling: define qual estado precisa ser alcançado.

Resultado

Sincronização orientada a estado tende a produzir testes mais rápidos, legíveis e resistentes às variações normais entre máquina local e CI. Mais importante: quando ocorre uma falha, a mensagem está relacionada à condição de negócio ou de interface que não foi satisfeita, e não a uma pausa escolhida arbitrariamente.

Aplicação prática

Veja este conceito em um projeto real.

Este artigo está relacionado ao Playwright Starter Lab, onde o conceito aparece aplicado em código.

Conhecer o projeto
Ver código no GitHub Todos os artigos
Continue estudando

Artigos relacionados

← AnteriorPassa localmente, falha no CI: investigando flakiness com PlaywrightPróximo →Page Object Model sem abstrações desnecessárias