O que são evidências e observabilidade em testes de API
Em testes de API, evidência é o conjunto de informações registradas que permite entender e reproduzir um comportamento observado (sucesso, falha ou degradação). Observabilidade é a capacidade de responder perguntas sobre o que aconteceu e por quê, usando sinais como logs, métricas e traces (rastros distribuídos). Na prática, para quem testa, observabilidade significa: conseguir ligar uma falha vista no teste a um evento no servidor, em um horário específico, dentro de um ambiente específico, com um identificador que conecte tudo.
Uma evidência de qualidade reduz o “vai e volta” com desenvolvimento e operações, porque responde rapidamente: o que foi enviado, o que foi recebido, em que contexto e como rastrear no backend.
O que registrar como evidência (checklist essencial)
1) Request e response sanitizados (sem segredos)
Registre request/response completos o suficiente para reproduzir, mas sanitizados para não expor dados sensíveis. O objetivo é manter estrutura e valores relevantes, removendo ou mascarando segredos e PII.
- Sanitizar: tokens, senhas, chaves, cookies, números de documento, e-mails, telefones, dados financeiros, etc.
- Preservar: campos que influenciam a regra (ex.: tipo, status, flags, ids técnicos), e o formato do payload.
// Exemplo de request sanitizado (JSON) para evidência
{
"method": "POST",
"url": "https://api.exemplo.com/v1/orders",
"headers": {
"Content-Type": "application/json",
"Accept": "application/json",
"X-Correlation-Id": "c0a8012e-2b7f-4f2a-9b7b-9d3b2b4f6a10"
},
"body": {
"customerId": "12345",
"payment": {
"cardToken": "***MASKED***"
},
"items": [
{"sku": "ABC-001", "qty": 2}
]
}
}// Exemplo de response sanitizado
{
"status": 500,
"headers": {
"Content-Type": "application/json",
"X-Correlation-Id": "c0a8012e-2b7f-4f2a-9b7b-9d3b2b4f6a10"
},
"body": {
"error": {
"code": "INTERNAL_ERROR",
"message": "Unexpected error"
}
}
}2) Headers relevantes
Nem todos os headers são úteis como evidência. Priorize os que ajudam a reproduzir e diagnosticar:
- Identidade e rastreio:
X-Correlation-Id(ou equivalente),traceparent(W3C Trace Context),X-Request-Id. - Contexto de execução:
User-Agent(cliente),X-Client-Version(se existir),X-Forwarded-For(quando relevante),Host. - Negociação/serialização:
Content-Type,Accept(apenas se impactarem o problema). - Cache e concorrência (quando aplicável):
If-Match,ETag,Cache-Control.
Evite registrar Authorization, Cookie e chaves de API em texto puro. Se precisar provar que houve autenticação, registre apenas “presente/ausente” e o tipo (ex.: “Bearer ***MASKED***”).
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
Baixar o aplicativo
3) Correlation-ID (ID de correlação)
O Correlation-ID é um identificador único que você envia na requisição e que o servidor propaga nos logs (e idealmente em chamadas internas). Ele permite encontrar rapidamente, no backend, o que aconteceu com aquela requisição específica.
- Ajuda a rastrear falhas em sistemas distribuídos.
- Ajuda a diferenciar bug (lógica) de problema de ambiente (instabilidade, dependências fora, configuração, rede).
- Reduz ambiguidade quando há alta concorrência (muitas requisições parecidas).
4) Timestamps e fuso horário
Registre timestamps em formato padronizado (ex.: ISO 8601 em UTC) para correlacionar com logs e métricas. Inclua:
- Início e fim da chamada
- Duração (latência observada)
- Fuso (preferencialmente UTC)
// Exemplo de metadados de tempo
{
"startedAt": "2026-01-26T13:45:12.345Z",
"finishedAt": "2026-01-26T13:45:12.912Z",
"durationMs": 567
}5) Ambiente e contexto de execução
Muitas “falhas” são variações de ambiente. Sempre registre:
- Ambiente: dev/hml/stg/prod (ou nome real)
- Base URL e região (se multi-região)
- Versão do serviço (build, commit, tag) quando disponível
- Configuração relevante: feature flags, tenant, perfil do usuário (sem dados sensíveis)
- Dependências (se conhecidas): serviço X/Y, fila, banco, provedor externo
| Item | Exemplo | Por que importa |
|---|---|---|
| Ambiente | staging-eu | Diferenças de config e dados |
| Versão | orders-service 1.18.3 (commit abc123) | Reproduzir em build específico |
| Tenant/Conta | tenantId=acme | Regras e dados variam por tenant |
| Feature flag | newPricing=true | Comportamento muda por flag |
Passo a passo: como coletar evidências úteis em um teste de API
Passo 1 — Gere e propague um Correlation-ID
Defina um padrão para o ID (UUID é suficiente) e envie em todas as requisições do teste. Se a API já gera um ID, capture o retornado e use-o como referência.
- Envio: header
X-Correlation-Id(ou o padrão da sua organização). - Validação: verifique se a resposta ecoa o mesmo ID (quando suportado).
// Exemplo (pseudo) de geração
X-Correlation-Id: 2f1c2b2a-6f2d-4b9a-9d6a-2a0d2f6c9a11Passo 2 — Registre request/response com sanitização automática
Implemente uma camada de logging no seu cliente de teste (ou no framework) que:
- Capture método, URL, query, headers relevantes e body
- Masque campos e headers sensíveis
- Trunque payloads muito grandes (com indicação de truncamento)
// Exemplo de regras de sanitização (lista de chaves)
SENSITIVE_HEADERS = ["authorization", "cookie", "x-api-key"]
SENSITIVE_FIELDS = ["password", "token", "cardNumber", "cardToken", "cpf", "ssn"]
MASK = "***MASKED***"Passo 3 — Capture metadados de tempo e rede
Além do timestamp, registre informações que ajudam a separar falha funcional de falha de infraestrutura:
- DNS/host resolvido (quando aplicável)
- IP/cluster (se disponível via header de resposta)
- Tempo de conexão vs tempo total (se o cliente expõe)
- Timeout configurado
Passo 4 — Ao falhar, gere um “pacote de evidência” mínimo
Quando um teste falha, gere automaticamente um artefato (arquivo JSON/texto) contendo:
- Correlation-ID
- Request/response sanitizados
- Timestamps e duração
- Ambiente, base URL, versão do serviço (se disponível)
- Asserção que falhou (o que era esperado vs obtido)
// Estrutura sugerida de pacote de evidência
{
"testCaseId": "API-ORDERS-017",
"environment": "staging-eu",
"baseUrl": "https://api.exemplo.com",
"serviceVersion": "orders-service 1.18.3",
"correlationId": "2f1c2b2a-6f2d-4b9a-9d6a-2a0d2f6c9a11",
"time": {
"startedAt": "2026-01-26T13:45:12.345Z",
"durationMs": 567
},
"request": { "method": "POST", "path": "/v1/orders", "headers": {"X-Correlation-Id": "..."}, "body": {"cardToken": "***MASKED***"} },
"response": { "status": 500, "headers": {"X-Correlation-Id": "..."}, "body": {"error": {"code": "INTERNAL_ERROR"}} },
"assertion": {
"expected": "HTTP 201 com body contendo orderId",
"actual": "HTTP 500 INTERNAL_ERROR"
}
}Como usar Correlation-ID para rastrear falhas e diagnosticar
Rastreamento no backend (fluxo mental)
Com o Correlation-ID em mãos, o fluxo típico de diagnóstico é:
- 1) Encontrar o log de entrada (gateway/API) pelo ID
- 2) Verificar validações iniciais (schema, autenticação, autorização, rate limit) e o status retornado
- 3) Seguir logs/traces para chamadas internas (serviços e dependências)
- 4) Identificar o ponto exato da falha (exceção, timeout, resposta inválida de dependência)
Mesmo sem acesso direto aos logs, fornecer o Correlation-ID no defeito permite que quem tem acesso encontre rapidamente o rastro.
Diferenciando bug de ambiente (heurísticas práticas)
| Sinal | Indica mais | Como evidenciar |
|---|---|---|
| Falha intermitente (passa/falha sem mudança) | Ambiente/instabilidade | Registrar frequência, horários, Correlation-IDs de múltiplas ocorrências |
| Timeouts e latência muito variável | Ambiente/dependência | Registrar durationMs, timeout configurado, status/erro de rede |
| Falha determinística com mesmo payload | Bug funcional | Fornecer exemplo mínimo reproduzível e passos consistentes |
| Erro concentrado em um nó/região | Ambiente/configuração | Registrar headers de identificação de instância/cluster (se existirem) |
| Erro após deploy/feature flag | Bug/regressão ou config | Registrar versão do serviço e flags ativas |
Quando coletar mais de um Correlation-ID
Em falhas intermitentes, um único ID pode não ser suficiente. Colete:
- Um ID de uma execução que falhou
- Um ID de uma execução equivalente que passou (mesmo endpoint e payload, se possível)
- Horários próximos
Isso ajuda a comparar caminhos de execução e dependências.
Padrão de relatório de defeito focado em API
Um bom relatório de defeito em API é objetivo, reproduzível e rastreável. Use um template padronizado para reduzir omissões.
Template (copiar e preencher)
Resumo:
- [Serviço] [Endpoint] retorna [status/erro] ao [condição]
Ambiente:
- Ambiente:
- Base URL:
- Região/Cluster (se aplicável):
- Versão do serviço/build:
- Feature flags/tenant:
Requisição:
- Método:
- Endpoint (path):
- Query params:
- Headers relevantes (sanitizados):
- Payload (sanitizado):
Resultado esperado:
- Status HTTP esperado:
- Corpo esperado (regra/contrato):
Resultado obtido:
- Status HTTP obtido:
- Corpo obtido (sanitizado):
- Headers de resposta relevantes:
Evidências e rastreio:
- Correlation-ID:
- Timestamps (UTC):
- Duração (ms):
- Logs do cliente (se houver):
Exemplo mínimo reproduzível:
- Passos (1..N):
- Dados mínimos para reproduzir:
- Observações sobre intermitência (frequência, janelas de tempo):Exemplo preenchido (mínimo e reproduzível)
Resumo:
- POST /v1/orders retorna 500 ao criar pedido com item válido
Ambiente:
- Ambiente: staging-eu
- Base URL: https://api.exemplo.com
- Versão do serviço/build: orders-service 1.18.3 (commit abc123)
- Tenant: acme | Feature flag: newPricing=true
Requisição:
- Método: POST
- Endpoint: /v1/orders
- Headers: Content-Type: application/json; Accept: application/json; X-Correlation-Id: 2f1c2b2a-6f2d-4b9a-9d6a-2a0d2f6c9a11
- Payload (sanitizado): {"customerId":"12345","payment":{"cardToken":"***MASKED***"},"items":[{"sku":"ABC-001","qty":2}]}
Resultado esperado:
- Status: 201
- Body: conter orderId e status=CREATED
Resultado obtido:
- Status: 500
- Body: {"error":{"code":"INTERNAL_ERROR","message":"Unexpected error"}}
Evidências e rastreio:
- Correlation-ID: 2f1c2b2a-6f2d-4b9a-9d6a-2a0d2f6c9a11
- Timestamp (UTC): 2026-01-26T13:45:12.345Z
- Duração: 567ms
Exemplo mínimo reproduzível:
1) Enviar POST /v1/orders com o payload acima
2) Repetir 3 vezes (falha 3/3)
Observação: determinístico neste ambiente; em dev não reproduziu.Critérios de qualidade de evidência (o que torna a evidência “boa”)
Critérios objetivos
- Reprodutibilidade: alguém consegue reproduzir com os dados fornecidos (ou entender por que é intermitente).
- Rastreabilidade: há Correlation-ID e timestamps para localizar logs/traces.
- Completude mínima: inclui endpoint, método, payload, headers relevantes, status esperado/obtido.
- Sanitização: não expõe segredos nem PII; mascaramento consistente.
- Precisão: não há contradições (ex.: status no texto diferente do status no log).
- Contexto de ambiente: base URL, ambiente, versão/build, flags/tenant quando influenciam.
- Foco no sinal: evita excesso de ruído (logs gigantes sem recorte); destaca o que falhou.
Anti-padrões comuns (e como corrigir)
| Anti-padrão | Problema | Correção |
|---|---|---|
| “Deu erro 500” sem request | Não reproduz nem diagnostica | Adicionar request/response sanitizados + esperado/obtido |
| Sem Correlation-ID | Backend não encontra o evento | Gerar/enviar ID e registrar na evidência |
| Print com token/senha | Risco de segurança | Sanitização automática e revisão |
| Payload enorme sem recorte | Ruído; difícil achar causa | Fornecer exemplo mínimo reproduzível |
| Sem ambiente/versão | “Não reproduz aqui” vira impasse | Registrar base URL, ambiente, build, flags |
Práticas recomendadas para padronizar evidências no time
Convenções de nomenclatura e armazenamento
- Nomear artefatos com
testCaseId, data/hora UTC ecorrelationId(ex.:API-ORDERS-017_20260126T134512Z_2f1c2b2a.json). - Armazenar evidências em local central com retenção definida (evitar espalhar em chats).
- Separar evidência de execução bem-sucedida vs falha para comparação.
Campos padrão para logs do cliente de teste
Se você controla o cliente de teste, padronize um log estruturado (JSON) com campos fixos. Isso facilita busca e agregação.
// Log estruturado sugerido (por requisição)
{
"level": "INFO",
"event": "api_call",
"testCaseId": "API-ORDERS-017",
"correlationId": "2f1c2b2a-6f2d-4b9a-9d6a-2a0d2f6c9a11",
"env": "staging-eu",
"method": "POST",
"path": "/v1/orders",
"status": 500,
"durationMs": 567,
"timestamp": "2026-01-26T13:45:12.912Z"
}Quando anexar evidências adicionais
Alguns cenários pedem evidências extras além de request/response:
- Intermitência: anexar série temporal (lista de tentativas com timestamps, status e durations).
- Dependência externa: registrar status/erro da dependência quando exposto (ex.: código de erro interno mapeado).
- Problema de serialização: anexar payload bruto (sanitizado) e o tipo de encoding.
- Problema de roteamento: anexar headers que identifiquem instância/edge (quando existirem).