Testes de Desempenho: como projetar, automatizar e validar performance em pipelines modernos
Testes de desempenho são uma família de testes que avaliam latência, throughput, erros e consumo de recursos sob uma carga definida — cobrindo carga, estresse, endurance (soak), spike e escalabilidade. Em arquiteturas distribuídas com cache, filas e múltiplas dependências, performance é um comportamento emergente. Por isso, testes de desempenho deixaram de ser um evento pontual de pré go-live e viraram um mecanismo contínuo de engenharia.
Todo time já viu o mesmo filme: a entrega está "funcionando", o deploy passa, e a aplicação cai quando o tráfego sai do padrão. Este guia cobre como planejar testes que medem o que importa, instrumentar a aplicação para encontrar gargalos com rapidez, e automatizar gates de performance na CI/CD. O cenário de referência é uma Black Friday em um SaaS com microserviços, com um painel de observabilidade mostrando latência, erros, saturação e filas em tempo real.
O que são testes de desempenho e por que falham na prática
O erro mais comum é tratar "desempenho" como sinônimo de "tempo de resposta", ignorando taxa de erros, saturação de CPU, pool de conexões, GC e limites de dependências.
Um teste falha na prática quando responde a uma pergunta vaga, como "aguenta 10 mil usuários?". A pergunta correta tem condições: qual jornada, qual mix de endpoints, qual perfil de chegada (aberto ou fechado), quais regiões, quais dados, qual cache warm, e qual SLO precisa ser mantido.
Regra de decisão por tipo de teste:
- Carga: valida SLO em tráfego esperado.
- Estresse: encontra o ponto de ruptura e o modo de falha.
- Endurance: detecta vazamentos, degradação e efeitos cumulativos.
- Spike: valida autoscaling, rate limit e comportamento de filas.
Em cloud, performance e eficiência se conectam: você quer atender o usuário com o mínimo de recursos possíveis e continuar eficiente quando a demanda muda. Essa visão está no pilar de Performance Efficiency do AWS Well-Architected Framework.
Como definir SLOs e SLIs antes de escrever qualquer script
Se você começar pelos scripts, vai terminar discutindo números sem contexto. Comece pelos acordos com o usuário: SLO (objetivo), SLI (métrica) e orçamento de erro. SLO nunca é 100%, porque o que sobra vira orçamento de erro para mudanças e risco controlado.
Workflow de especificação (30 a 90 minutos)
1. Escolha 3 jornadas críticas (ex.: login, busca, checkout). Evite listar endpoints — foque em fluxos.
2. Defina SLIs por jornada:
- Latência: p95 e p99 (não média).
- Taxa de erro: HTTP 5xx, timeouts, falhas de dependências.
- Throughput: req/s ou transações/minuto.
3. Converta em SLO testável:
| Jornada | SLI | SLO |
|---|---|---|
| Login | Latência p95 | < 400 ms |
| Checkout | Taxa de erro | < 1% |
| Busca | Sucesso | 99% das requisições |
A documentação do Grafana k6 recomenda codificar SLOs em critérios pass/fail (thresholds), com exemplos como "95% abaixo de 200 ms" e "erros abaixo de 1%".
4. Modele a carga (o "shape" do tráfego):
- Ramp-up, patamar, ramp-down.
- Aberto (arrival rate) vs. fechado (usuários concorrentes).
Regra de decisão:
- Tráfego público e infinito (landing pages, APIs abertas): prefira modelo aberto.
- Existe fila natural (checkouts, backoffice, limites de sessão): modelo fechado costuma revelar contenção.
5. Estabeleça critérios de parada: "interromper se erro > 5% por 2 minutos" ou "interromper se p95 dobra". Isso evita testes que só geram ruído.
Stack de ferramentas para testes de desempenho
Ferramenta é meio, não estratégia. A escolha certa depende de linguagem do time, protocolo, necessidade de testes distribuídos e integração com CI.
Matriz de escolha por perfil de time
| Ferramenta | Melhor para | Destaque |
|---|---|---|
| Grafana k6 | Testes como código em JS, gates na CI | Thresholds nativos, integração com Grafana Cloud |
| Apache JMeter | Times com GUI, ecossistema consolidado | Execução distribuída para alta escala |
| Gatling | Alta concorrência com baixo overhead | SDKs, simulações e perfis de injeção |
| Locust | Times Python, comportamento flexível | Wait time, pesos por perfil, código limpo |
| Artillery | Times JS/TS, tráfego por fases | Integração com CI e observabilidade |
O painel de controle que evita caça ao bug
Sem observabilidade, testes de desempenho viram um teste cego: você mede sintomas, não causas. O mínimo viável:
- Métricas de infra e aplicação: CPU, memória, GC, pool de conexões, fila, cache hit.
- Tracing distribuído para microserviços: enxergar a cadeia completa da requisição.
O OpenTelemetry virou padrão de mercado para instrumentar e exportar traces, métricas e logs, com Collector no meio para processar e enviar aos backends. Para métricas, Prometheus é referência em timeseries e alertas, e se integra com visualização no Grafana.
Testes de desempenho na CI/CD: gates de performance sem travar o time
A mudança que mais traz resultado é transformar testes de desempenho em um sistema de feedback contínuo. Isso não significa rodar um teste de 2 horas a cada pull request — significa separar testes por finalidade e custo.
Blueprint de pipeline
PR / feature branch (5 a 10 min)
- Smoke de performance: 1 cenário crítico, carga pequena, thresholds rígidos.
- Objetivo: detectar regressões óbvias (query N+1, endpoint sem cache).
Main branch / nightly (30 a 90 min)
- Carga representativa com mix de jornadas.
- Objetivo: validar SLO e tendência (p95 não pode subir semana a semana).
Pré-release (2 a 4 h, agendado)
- Estresse + endurance.
- Objetivo: ponto de ruptura, modos de falha, vazamentos.
Como codificar gates sem falso positivo
No k6, thresholds viram critérios objetivos de aprovação. A documentação reforça que thresholds são essenciais para automação e para transformar SLO em pass/fail.
Evite "um único número" para aprovar release. Use um conjunto pequeno e robusto:
- p95 e p99 (latência)
- Taxa de erro
- Um indicador de saturação (CPU, pool, fila)
Amarre isso ao seu processo de risco. A lógica de orçamento de erro ajuda a decidir quando segurar deploy e quando seguir — a política está detalhada no material público do Google SRE.
Diagnóstico em microserviços: do sintoma ao gargalo em 30 minutos
No cenário da Black Friday, você vai ver o p95 do checkout subir, mas a causa pode estar em outro lugar: fila crescendo, cache derrubado, pool de conexões esgotado, lock no banco, ou uma dependência externa mais lenta.
Workflow de diagnóstico
1. Confirme se a carga é realista
- Warm-up aconteceu?
- Dados e permissões representam produção?
- O mix de jornadas bate com analytics?
2. Localize o gargalo por classe
| Sintoma | Causa provável |
|---|---|
| CPU alta, throughput travado | Contenção ou hot path |
| Memória crescendo | Leak, cache sem TTL, objetos grandes |
| Latência sobe, CPU estável | Espera externa (DB, rede, dependência) |
3. Use tracing para fechar o mapa
Com OpenTelemetry, você padroniza a correlação entre sinais e consegue ligar spans, recursos e contexto — reduzindo drasticamente o tempo até a causa raiz.
4. Valide a hipótese com um microteste
Reduza o escopo para um endpoint. Compare antes e depois com o mesmo shape de tráfego.
Exemplo de resultado após correção:
| Métrica | Antes | Depois |
|---|---|---|
| p95 checkout | 1.200 ms | 450 ms |
| Taxa de erro | 2,5% | 0,3% |
| Fila média | 8.000 msgs | 500 msgs |
Esse é o momento em que o painel de controle deixa de ser bonito e vira ferramenta de decisão.
QA e cobertura: como evitar testes que passam e não protegem ninguém
Para um time de QA, "cobertura" em testes de desempenho não é quantidade de endpoints. É cobertura de risco: jornadas críticas, variações de dados e limites de infraestrutura.
Checklist de validação
- Validação funcional sob carga: resposta correta, não só rápida.
- Dados de teste realistas: cardinalidade, tamanhos, distribuição.
- Ambiente representativo: versão de banco, índices, cache, limites de rede.
- Isolamento de ruído: jobs paralelos, autoscaling configurado, vizinhança.
Cobertura por perfil de usuário
Com Locust, pesos por tipo de usuário e tempos de espera permitem modelar comportamento com realismo, em vez de disparar requests sem pausa. Com Artillery, fases com arrivalRate e ramp representam tráfego que cresce em ondas — comum em campanhas e picos.
Regra de decisão para evitar autoengano:
- Se o teste não consegue explicar "por que piorou", ele está incompleto.
- Se o teste só mede
/healthe/login, ele não protege receita.
Observabilidade não é só coleta — é correlação. Conectar traces, métricas e logs reduz drasticamente o tempo até a causa raiz.
Próximos passos
Escolha uma jornada crítica, defina um SLO com p95 e taxa de erro, e rode um teste pequeno diariamente na CI. Em paralelo, monte seu painel com Prometheus, Grafana e OpenTelemetry para transformar resultados em decisões. Comece com thresholds claros no seu runner e só depois aumente escala e complexidade. Quando isso estiver estável, adicione estresse e endurance para achar modos de falha antes do usuário. O objetivo não é "passar no teste" — é criar confiança para entregar com velocidade.