12k
All articles

Smoke Tests e Por Que os Agentes Insistem em Escrevê-los

Smoke tests explicados: o que verificar, onde executar, o que excluir e por que agentes de código continuam adicionando-os ao CI e aos deploys.

OpenReplay Team
OpenReplay Team
Smoke Tests e Por Que os Agentes Insistem em Escrevê-los

Um smoke test é um pequeno conjunto de verificações que atesta se um sistema implantado está fundamentalmente vivo: o processo iniciou, a página principal retorna 200, um usuário consegue fazer login e o banco de dados responde a uma consulta. Ele não julga se o software está correto; ele decide se vale a pena gastar tempo executando o restante da suíte de testes.

Se você entrega para CI há anos sem nunca ter precisado dessa definição, você não está sozinho. A expressão costuma aparecer sem apresentações, e ultimamente ela aparece dentro de um pull request: um smoke.sh ou smoke.spec.ts que um agente de código adicionou enquanto finalizava outra coisa.

Este artigo cobre o que deve fazer parte de um smoke test, onde ele roda, como é um exemplo mínimo em código, o filtro para manter coisas fora dele e por que os agentes os produzem com tanta consistência.

Principais Conclusões

  • Um smoke test verifica se um sistema implantado está vivo (boot, 200 na página principal, login, uma leitura real no banco de dados) e leva segundos, não minutos.
  • Ele roda duas vezes: como primeiro gate no CI e imediatamente após um deploy, contra o ambiente para o qual o deploy foi realmente feito; uma execução em localhost não consegue capturar falhas de deployment.
  • Uma verificação pertence à suíte de smoke apenas se sua falha bloqueia todos os usuários, todos os usuários passam por ela e ela pode quebrar durante o deployment. Se atender a menos que os três critérios, vai para a suíte de regressão.
  • Agentes de código escrevem smoke tests porque uma tarefa concluída precisa de um sinal barato, binário e rápido de que nada fundamental quebrou, que é exatamente o que um smoke test produz.
  • Defina um teto rígido para a suíte e mova tudo que exceder esse limite para a regressão; uma suíte de smoke de doze minutos é uma suíte de regressão com o nome errado.

O Que É um Smoke Test?

Um smoke test responde a uma única pergunta, “esta build está viva o suficiente para ser testada mais a fundo?”, e seu nome é comumente atribuído ao ato de ligar um hardware novo e observar se sai fumaça. No software a forma é a mesma: uma passagem rápida e superficial pelos caminhos dos quais todo usuário depende, com um resultado binário e sem nenhuma opinião sobre correção.

Ele fica fora da pirâmide de testes usual, em vez de em uma de suas camadas; as camadas em si são abordadas em Integration Tests vs End-to-End Tests e Unit vs Integration Testing in JavaScript: What to Use When. Um smoke test é um gate na frente dessas suítes, não um membro delas.

Onde o Smoke Testing Roda?

Smoke tests rodam em dois lugares: como o primeiro gate no CI, antes que suítes mais longas comecem, e imediatamente após um deployment, contra o ambiente para o qual o deploy foi realmente feito. O segundo posicionamento é o que justifica sua existência, e é o mais frequentemente ignorado.

Rodar um smoke test contra localhost anula seu propósito, porque as falhas que ele existe para capturar só acontecem no deployment: uma variável de ambiente ausente, uma migration que nunca rodou, um bundle de assets que nunca foi publicado. Um processo iniciado no runner do CI com APP_URL=localhost e um banco de dados em memória novo em folha não tem nenhum desses modos de falha disponíveis. Esse tipo de execução é uma verificação de boot, e verificações de boot são úteis, mas são uma coisa diferente e mais fraca. Uma execução local contra serviços mockados não pode falhar por nenhuma das razões pelas quais um deployment falha, então não deveria levar esse nome.

A execução pós-deploy também é o gatilho natural para rollback: o AWS CodeDeploy executa sua função de validação assim que a nova versão está servindo tráfego de teste, e um resultado falho dela dispara um rollback. Tenha em mente, porém, o limite desse sinal. Um smoke test pós-deploy verde prova que o sistema respondeu, não que a jornada do usuário funciona; assistir a session replays das primeiras sessões reais após um release é a técnica que separa as duas coisas, porque um botão de checkout que lança um erro por causa de um hash de chunk alterado nunca aparece em um status code.

Como É um Smoke Test?

Uma suíte de smoke completa pode ser um único script curto que atinge o alvo real implantado sem mocks: uma espera limitada pelo endpoint de health, uma requisição autenticada e uma leitura que passa pela aplicação até o banco de dados.

#!/usr/bin/env bash
# smoke.sh: runs against the deployed target in $APP_URL, never localhost
set -euo pipefail

: "${APP_URL:?set APP_URL to the deployed base URL}"
: "${SMOKE_USER:?}" "${SMOKE_PASS:?}"

status() { curl --silent --output /dev/null --write-out '%{http_code}' "$@"; }

# 1. Wait for the process to come up. This absorbs container start-up, nothing else.
for _ in $(seq 1 "${SMOKE_RETRIES:-10}"); do
  [ "$(status "$APP_URL/health")" = "200" ] && break
  sleep 3
done
[ "$(status "$APP_URL/health")" = "200" ] || { echo "health: not 200"; exit 1; }

# 2. Login. Assert the one status your app returns (200 for a JSON API, 302 for a form post).
code=$(status --data-urlencode "email=$SMOKE_USER" \
              --data-urlencode "password=$SMOKE_PASS" "$APP_URL/login")
[ "$code" = "200" ] || { echo "login: got $code, expected 200"; exit 1; }

# 3. A real read through the app, with the credentials the app was deployed with.
body=$(curl --silent --fail "$APP_URL/api/products?limit=1") || { echo "query: request failed"; exit 1; }
[ -n "$body" ] || { echo "query: empty body"; exit 1; }

echo "smoke: ok"

O helper status usa o --write-out '%{http_code}' do curl para capturar o código de resposta, enquanto --output /dev/null descarta o corpo. set -euo pipefail faz o script encerrar na primeira falha. O loop de retry existe apenas para absorver o tempo de inicialização após um deploy; não é uma forma de disfarçar uma verificação instável.

Cada asserção nomeia exatamente um status. Todo código na RFC 9110 carrega um significado, então uma verificação que aceita “qualquer resposta” não é uma verificação: um 404 vindo de uma rota que deveria existir é uma falha de deployment, e um 302 só é aceitável onde o contrato é um redirecionamento. A terceira verificação importa mais do que parece. Fazer um ping no servidor de banco de dados com uma ferramenta como pg_isready confirma que o servidor aceita conexões; uma leitura através da aplicação confirma que o app consegue alcançar o banco de dados com a connection string, as credenciais e o schema com os quais foi implantado, que é a classe de falha para a qual os smoke tests existem.

O Que Não Pertence a um Smoke Test

Casos extremos, regras de negócio, qualquer coisa lenta e qualquer coisa instável não pertencem a um smoke test. Uma verificação pertence à suíte de smoke apenas se as três condições forem verdadeiras: sua falha impede todos os usuários de fazer qualquer coisa, todos os usuários passam por ela, e ela pode quebrar durante um deployment. Uma verificação que atende a menos de três pertence à suíte de regressão. Esse enquadramento de três perguntas aparece na orientação de ao menos um fornecedor de testes em CI, e é uma heurística e não um padrão.

Verificação candidataBloqueia todos os usuários?Todos os usuários passam por ela?Quebra no deploy?Veredito
Endpoint de health retorna 200SimSimSimSmoke
Login com uma conta de testeSimSimSimSmoke
Código de cupom aplica um descontoNãoNãoSimRegressão
Exportação de CSV do admin é baixadaNãoNãoSimRegressão
E-mail de redefinição de senha chegaNãoNãoSimRegressão

A instabilidade é desqualificante por si só. Uma verificação de smoke que falha aleatoriamente ensina o time a reexecutar gates vermelhos, e um gate que as pessoas reexecutam até passar deixa de ser um gate.

Por Que os Agentes de Código Insistem em Escrever Smoke Tests?

Agentes de código escrevem smoke tests porque um agente que finaliza uma tarefa precisa de um sinal barato, rápido e inequívoco de que não quebrou o sistema inteiro, e esse é exatamente o sinal que um smoke test produz. Um agente que acabou de editar código não pode arcar com a suíte completa a cada iteração e não consegue julgar correção por inspeção, então recorre à verificação que responde “ainda está vivo?” em segundos e retorna um exit code limpo.

Isso não é acidental. A documentação do Claude Code da Anthropic orienta os desenvolvedores a entregar ao agente algo que ele possa executar para conferir o próprio trabalho, seja uma suíte de testes, um build, um linter ou um pequeno script. Dado um sinal que ele mesmo pode ler, o agente continua trabalhando e reverificando sem esperar que uma pessoa aponte o erro. Um script de smoke se encaixa bem nessa descrição, e é por isso que repositórios escritos por agentes tendem a ganhar um, mesmo quando o time nunca usou o termo. Essa é a razão pela qual os desenvolvedores estão encontrando “smoke test” agora, muitas vezes ao descobrir um em um diff que não escreveram.

Quando um aparece em um PR, revise-o com base em quatro perguntas. Ele lê a URL alvo de uma variável de ambiente em vez de hardcodar localhost? Ele afirma um status específico em vez de “não é um erro”? Ele termina em segundos? Cada verificação passa no filtro das três perguntas acima? Um smoke test escrito por agente que falhe em qualquer uma delas é ou uma verificação de boot ou um teste de regressão usando o rótulo errado.

O Modo de Falha: A Suíte Cresce

Uma suíte de smoke deixa de ser um gate no momento em que passa de alguns segundos. O padrão é previsível: cada feature adiciona uma verificação “por via das dúvidas”, um agente adiciona outra depois de cada tarefa, e um dia o gate leva doze minutos e as pessoas começam a pulá-lo. Nesse ponto, ela é uma suíte de regressão lenta com o nome errado.

A solução é um teto rígido, com tudo acima dele movido para a regressão. Nosso padrão recomendado é um punhado de verificações, da ordem de cinco, que terminam em segundos; a TestingXperts coloca o limite externo em dez minutos, a partir do qual os times começam a pular o gate. O número exato importa menos do que ter um número escrito e aplicado na revisão, incluindo a revisão de adições feitas por agentes.

Conclusão

Um smoke test é a menor prova possível de que um deployment está vivo: health, login, uma leitura real, executados contra o ambiente para o qual você de fato entregou, concluídos em segundos. Todo o resto é regressão. Na próxima vez que um agente te entregar um smoke.sh, verifique se ele aponta para uma URL real, afirma status exatos e permanece abaixo do teto, e então configure-o para rodar após cada deploy.

FAQs

Qual é a diferença entre um smoke test e um health check?

Um health check é um endpoint que um orquestrador ou load balancer consulta periodicamente para decidir se roteia tráfego ou reinicia um container; o Kubernetes chama isso de liveness e readiness probes. Um smoke test roda uma vez por deployment, chama esse endpoint mais um login e uma leitura no banco de dados, e retorna um exit code que controla o pipeline. O endpoint de health é a primeira asserção do smoke test, não um substituto para ele.

Qual é a diferença entre smoke testing e sanity testing?

Smoke testing é amplo e superficial: verifica se os caminhos centrais de uma build estão vivos antes que testes mais profundos comecem. Sanity testing, na terminologia convencional de QA, é estreito e profundo: verifica se uma correção ou alteração específica funciona em uma build que já passou pelo smoke, e frequentemente é considerado um subconjunto dos testes de regressão. Em um pipeline de CI, a suíte de smoke é o gate; as verificações de sanity pertencem à regressão.

Smoke tests devem rodar contra produção, e isso é seguro?

Sim. A execução pós-deploy deve apontar para o ambiente que os usuários realmente acessam, incluindo produção, porque falhas de deployment só aparecem lá. Mantenha a segurança usando uma conta de teste dedicada e pré-populada, fornecida via secrets do CI, limitando as verificações a um login e requisições somente de leitura, e excluindo qualquer coisa que escreva dados ou envie e-mail. Se uma escrita for inevitável, restrinja-a a um tenant de teste e faça a limpeza no mesmo script.

Posso escrever um smoke test em Playwright ou Cypress em vez de um shell script?

Sim, desde que siga as mesmas regras: ler a URL base de uma variável de ambiente, afirmar status exatos ou elementos visíveis, e terminar em segundos. Executores de browser adicionam tempo de inicialização e de carregamento de página por verificação, então mantenha a suíte de smoke no browser limitada a uma ou duas jornadas e deixe as verificações HTTP no curl. Coloque a spec de smoke em seu próprio arquivo para que o CI possa executá-la sem o restante da suíte.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — self-hosted, with full data ownership.

Star on GitHub

We use cookies to improve your experience. By using our site, you accept cookies.