6 min

Depure relatórios de bugs que você não escreveu: um fluxo de trabalho prático

Depure relatórios de bugs que você não escreveu com um fluxo prático para reproduzir problemas, isolar UI/API/banco de dados e solicitar uma correção mínima e testável.

Depure relatórios de bugs que você não escreveu: um fluxo de trabalho prático

O que torna esses relatórios de bug difíceis (e o que você pode controlar)

Depurar um relatório de bug que você não escreveu é mais difícil porque falta o mapa mental do autor. Você não sabe o que é frágil, o que é “normal” ou quais atalhos foram tomados. Um sintoma pequeno (um botão, um erro de digitação, uma tela lenta) pode vir de um problema mais profundo na API, no banco de dados ou em um job em background.

Um relatório útil te dá quatro coisas:

  • a ação exata
  • os dados exatos
  • o resultado esperado
  • o resultado real

A maioria dos relatos só dá o último: “Salvar não funciona”, “está quebrado”, “erro aleatório”. Falta o contexto que torna o problema repetível: papel do usuário, registro específico, ambiente (prod vs staging) e se começou após alguma mudança.

O objetivo é transformar um sintoma vago em uma reprodução confiável. Uma vez que você consiga fazê-lo acontecer sob demanda, deixa de ser um mistério. É uma sequência de checagens.

O que você pode controlar de imediato:

  • o menor conjunto de passos que dispara o problema
  • os dados de teste exatos (IDs, e-mail, payload, filtros)
  • o ambiente e versão (build, feature flags, navegador/dispositivo)
  • prova de que aconteceu (timestamp, captura de tela, texto de erro, trecho de log)
  • um resultado claro de passou/falhou que você possa reexecutar

“Pronto” não é “acho que consertei”. Pronto é: seus passos de reprodução passam após uma pequena mudança, e você retesta rapidamente comportamentos próximos que poderia ter afetado.

Configure uma baseline estável antes de mexer em qualquer coisa

A maneira mais rápida de perder tempo é mudar várias coisas ao mesmo tempo. Congele seu ponto de partida para que cada resultado de teste signifique algo.

Escolha um ambiente e se mantenha nele até conseguir reproduzir o problema. Se o relato veio de produção, confirme lá primeiro. Se for arriscado, use staging. Local é ok se você conseguir reproduzir de perto os dados e configurações.

Depois, identifique qual código está realmente rodando: versão, data do build e quaisquer feature flags ou configs que afetem o fluxo. Pequenas diferenças (integrações desabilitadas, URL base da API diferente, jobs em background ausentes) podem transformar um bug real em um fantasma.

Crie um setup de teste limpo e repetível. Use uma conta nova e dados conhecidos. Se puder, resete o estado antes de cada tentativa (logout, limpar cache, começar do mesmo registro).

Anote suposições conforme avança. Isso não é trabalho inútil; evita que você discuta consigo mesmo depois.

Um template de nota de baseline:

  • Ambiente: prod, staging ou local
  • Versão/build: commit, tag ou timestamp do build
  • Config: feature flags, integrações, chaves de teste
  • Identidade de teste: e-mail/role da conta, permissões
  • Dados: IDs de registro, itens seedados, estado inicial esperado

Se a reprodução falhar, essas notas dizem o que variar a seguir, um botão de cada vez.

Traduza o relatório em passos e entradas testáveis

A vitória mais rápida é transformar uma reclamação vaga em algo que você pode rodar como um script.

Comece reescrevendo o relato como uma curta user story: quem faz o quê, onde e o que esperava. Depois adicione o resultado observado.

Exemplo de reescrita:

"Como administrador de cobrança, quando eu mudo o status de uma fatura para Pago e clico em Salvar na página da fatura, o status deve persistir. Em vez disso, a página permanece igual e o status não muda após o refresh."

Em seguida, capture as condições que tornam o relato verdadeiro. Bugs frequentemente dependem de um detalhe único: papel, estado do registro, localidade ou ambiente.

Entradas-chave para anotar antes de começar a clicar:

  • Papel do usuário e tipo de conta (admin vs padrão, trial vs pago)
  • Estado dos dados (ID do registro, status, dados relacionados necessários)
  • Detalhes do cliente (SO, versão do navegador/app)
  • Localidade e configurações de tempo (idioma, fuso horário, intervalo de datas)
  • Ambiente e build (prod vs staging, versão de release, feature flags)

Colete evidências enquanto ainda tiver o comportamento original. Capturas de tela ajudam, mas uma gravação curta é melhor porque captura timing e cliques exatos. Sempre anote um timestamp (incluindo fuso horário) para cruzar com os logs depois.

Três perguntas esclarecedoras que removem a maior parte das suposições:

  • Em qual conta de usuário e papel exato isso aconteceu, e você pode fornecer um ID de registro de exemplo?
  • O que você esperava ver imediatamente após a ação e o que viu de fato?
  • Acontece toda vez com os mesmos passos, ou apenas com dados específicos (status, intervalo de datas, localidade, entradas grandes)?

Reproduza o problema de forma confiável

Não comece chutando a causa. Faça o problema acontecer de propósito, da mesma forma, mais de uma vez.

Primeiro, siga os passos do repórter exatamente como escritos. Não “melhore” eles. Note o primeiro ponto onde sua experiência diverge, mesmo que pareça pequeno (label de botão diferente, campo faltando, texto de erro ligeiramente distinto). Essa primeira diferença é muitas vezes a pista.

Um fluxo simples que funciona na maioria das aplicações:

  • Restaure um estado inicial conhecido (carregamento limpo, mesma conta, mesmas permissões, mesmas flags).
  • Siga os passos um a um e registre as entradas exatas que usou (IDs, datas, filtros).
  • Anote esperado vs real no passo onde quebra.
  • Repita mais uma vez para confirmar que é reproduzível.
  • Reduza para o menor conjunto de passos que ainda o dispara.

Depois que for repetível, varie uma coisa por vez. Testes de variável única que normalmente valem a pena:

  • mesmos passos, papel diferente
  • mesmos passos, outro registro (novo vs legado)
  • mesmos passos, navegador/dispositivo diferente
  • mesmos passos, sessão limpa (incógnito, cache limpo)
  • mesmos passos, rede diferente

Termine com um curto script de repro que outra pessoa possa executar em 2 minutos: estado inicial, passos, entradas e a primeira observação falha.

Isole a camada que falha: UI, API ou BD

Valide a API e o BD
Prototipe o caminho da API e do banco de dados em Go e PostgreSQL para confirmar onde falha.

Antes de ler todo o código, decida qual camada está falhando.

Pergunte: o sintoma está apenas na UI, ou os dados e respostas da API também estão errados?

Exemplo: “Meu nome de perfil não atualizou.” Se a API retorna o nome novo mas a UI ainda mostra o antigo, suspeite de estado/caching na UI. Se a API nunca salvou, você provavelmente está em território de API ou BD.

Perguntas rápidas de triagem que você pode responder em minutos:

  • Você consegue reproduzir em mais de um navegador/dispositivo?
  • Um hard refresh muda algo?
  • Uma requisição de rede é disparada quando você clica no botão?
  • A resposta da API já parece errada?
  • O banco de dados mostra a linha esperada após a ação?

Checagens de UI são sobre visibilidade: erros no console, aba Network e estado obsoleto (UI não refaz fetch após salvar, ou lê de um cache antigo).

Checagens de API são sobre contrato: payload (campos, tipos, IDs), código de status e corpo de erro. Um 200 com um body surpreendente pode importar tanto quanto um 400.

Checagens de BD são sobre realidade: linhas faltando, gravações parciais, violação de constraints, updates que afetam zero linhas porque o WHERE não bate.

Para se orientar, desenhe um pequeno mapa: qual ação da UI dispara qual endpoint e quais tabelas ele lê ou escreve.

Siga a requisição ponta a ponta com logs e timestamps

A clareza frequentemente vem de seguir uma requisição real do clique até o banco e de volta.

Capture três âncoras do relato ou do seu repro:

  • tempo exato (com fuso horário)
  • identificador do usuário (conta/e-mail/ID interno)
  • correlation ID (request ID/trace ID/session ID)

Se não tiver correlation ID, adicione um no gateway/backend e inclua-o nos cabeçalhos de resposta e nos logs.

Para não se afogar em ruído, capture apenas o necessário para responder “Onde falhou e por quê?”:

  • intervalo de tempo (por exemplo, 1 minuto antes até 1 minuto depois)
  • um ID de usuário (e ID de tenant/org se relevante)
  • correlation ID
  • método, path, status code, latência
  • a primeira mensagem de erro significativa (não páginas de stack traces)

Sinais para observar:

  • Timeouts/latência alta: queries lentas, chamadas externas, locks.
  • 401/403: problemas de permissão ou contexto de tenant.
  • 400 erros de validação: frequentemente mismatch de payload vindo da UI.

Se “funcionou ontem” mas não hoje, suspeite de drift no ambiente: flags alteradas, segredos rotacionados, migrations faltando ou jobs que pararam de rodar.

Construa um caso mínimo reproduzível (para que correções fiquem pequenas)

O bug mais fácil de consertar é um experimento pequeno e repetível.

Reduza tudo: menos cliques, menos campos, o menor dataset que ainda falha. Se só acontece com “clientes com muitos registros”, tente criar um caso mínimo que ainda dispare. Se não conseguir, isso indica que o bug pode ser relacionado a volume de dados.

Separe “estado ruim” de “código ruim” resetando o estado de propósito: conta limpa, tenant/dataset novo, build conhecido.

Uma forma prática de manter o repro claro é uma tabela compacta de entradas:

Given (setup)When (action)ExpectGot
User role: Editor; one record with Status=DraftClick SaveToast "Saved" + updated timestampButton shows spinner then stops; no change

Faça o repro portátil para que outra pessoa possa rodar rápido:

  • 3 a 6 passos a partir de um início limpo
  • um registro de teste (ou um body de requisição) reutilizável
  • um sinal claro de sucesso (mensagem UI, código HTTP, contagem de linhas no BD)
  • detalhes exatos do ambiente (build/versão, role, flags)

Armadilhas comuns que fazem perder tempo

Corrija bugs a partir de um arquivo de caso
Transforme um arquivo de caso de bug em um patch focado via chat e verifique com um repro repetível.

O caminho mais rápido costuma ser entediante: mude uma coisa, observe, mantenha notas.

Erros comuns:

  • Consertar o sintoma superficial (mascarando um erro real de API/BD).
  • Mudar múltiplas variáveis ao mesmo tempo (atualizações de dependência + configs + refatoração).
  • Testar em uma baseline diferente da do repórter (env, dados, build, navegador).
  • Esquecer permissões e roles (admin vs usuário regular).
  • Ignorar feature flags ou experimentos que mudam o fluxo.
  • Declarar vitória sem verificação (não rerodar o repro, não checar efeitos colaterais).

Um exemplo realista: um ticket diz “Export CSV vem em branco.” Você testa com uma conta admin e vê dados. O usuário tem um papel restrito, e a API retorna uma lista vazia por um filtro de permissão. Se você só consertar a UI para dizer “Sem linhas”, perde a questão real: esse papel deve ter permissão para exportar, ou o produto deveria explicar por que está filtrado?

Após qualquer correção, reroda os passos exatos do repro e então teste um cenário próximo que deveria continuar funcionando.

Checklist rápido antes de pedir uma correção

Você terá respostas melhores de um colega (ou de uma ferramenta) se trouxer um pacote enxuto: passos reproduzíveis, uma camada provável que falha e prova.

Antes de qualquer um mudar código, confirme:

  • Você consegue reproduzir duas vezes usando os mesmos inputs (mesmo usuário, mesmos dados, mesmo ambiente).
  • Você consegue nomear a camada que falha (UI, API ou BD) e dar uma razão.
  • Você capturou evidências: requisição, resposta/erro, logs relevantes e um timestamp correspondente.
  • Você reduziu o repro ao menor caso possível.
  • Você escreveu critérios de aceitação em uma frase (exemplo: "Salvar atualiza o registro e mostra sucesso em até 2 segundos").

Então faça uma rápida verificação de regressão: tente um papel diferente, uma segunda janela/navegador privado, uma funcionalidade próxima que usa o mesmo endpoint/tabela e um input de borda (vazio, texto longo, caracteres especiais).

Um exemplo realista: estreitando um bug “Botão Salvar não faz nada”

Desfaça mudanças arriscadas com segurança
Se uma mudança der errado, reverta em segundos e continue a depuração a partir de um estado conhecido.

Uma mensagem de suporte diz: "O botão Salvar não faz nada no formulário Edit Customer." Um follow-up revela que só acontece para clientes criados antes do mês passado, e apenas quando você muda o e-mail de cobrança.

Comece pela UI e assuma a falha mais simples primeiro. Abra o registro, faça a alteração e procure sinais de que “nada” é na verdade algo: botão desabilitado, toast escondido, mensagem de validação que não renderiza. Depois abra o console do navegador e a aba Network.

Aqui, clicar em Salvar dispara uma requisição, mas a UI nunca mostra o resultado porque o frontend só trata 200 como sucesso e ignora erros 400. A aba Network mostra uma resposta 400 com um corpo JSON como: {\\\"error\\\":\\\"billingEmail must be unique\\\"}.

Agora verifique se a API realmente está falhando: pegue o payload exato da requisição e repita fora da UI. Se falhar também fora da UI, pare de perseguir bugs de estado do frontend.

Depois verifique o banco de dados: por que a unicidade falha apenas em registros antigos? Você descobre que clientes legados compartilham um billing_email placeholder de anos atrás. Uma checagem de unicidade mais nova agora bloqueia salvar qualquer cliente que ainda tenha esse placeholder.

Repro mínimo que você pode passar adiante:

  • Pegue um cliente legado com billing_email = [email protected].
  • Mude qualquer campo e clique em Salvar.
  • Observe que a API retorna 400 com billingEmail must be unique.
  • Observe que a UI não mostra erro e deixa o formulário inalterado.

Teste de aceitação: quando a API retornar um erro de validação, a UI exibe a mensagem, preserva as alterações do usuário e o erro aponta o campo exato que falhou.

Próximos passos: pedir uma correção mínima que você possa testar

Quando o bug estiver reproduzível e você identificou a camada provável, peça ajuda de forma a obter um patch pequeno e seguro.

Empacote um simples “arquivo de caso”: passos mínimos de repro (com inputs, ambiente, role), esperado vs real, por que você acha que é UI/API/BD, e o menor trecho de log que mostra a falha.

Então faça o pedido estreito:

  • proponha a menor mudança de código que corrige o repro
  • evite refatorações a menos que necessárias
  • explique a causa em linguagem simples
  • inclua um pequeno plano de testes (como confirmar a correção e o que pode quebrar por perto)

Se usar uma plataforma de vibe-coding como Koder.ai (koder.ai), essa abordagem de arquivo de caso mantém a sugestão focada. Os snapshots e rollback também ajudam a testar pequenas mudanças com segurança e voltar a uma baseline conhecida.

Passe para um desenvolvedor experiente quando a correção tocar em segurança, pagamentos, migrações de dados ou algo que possa corromper dados em produção. Também passe adiante se a mudança crescer além de um patch pequeno ou se você não conseguir explicar o risco em palavras simples.

Perguntas frequentes

Qual é a primeira coisa que devo fazer com um relatório vago como “está quebrado”?

Comece reescrevendo em um script reproduzível: quem (papel), onde (página/fluxo), quais entradas exatas (IDs, filtros, payload), o que você esperava e o que viu. Se faltar alguma dessas peças, peça uma conta de exemplo e um ID de registro para poder rodar o mesmo cenário de ponta a ponta.

Como eu defino uma baseline para que meus testes realmente signifiquem algo?

Escolha um único ambiente e permaneça nele até reproduzir. Registre a versão/build, feature flags, configuração, conta/role de teste e os dados exatos usados. Isso evita “corrigir” um bug que só existe porque sua configuração difere da do repórter.

Como transformo o relatório em uma reprodução mínima que outra pessoa possa rodar rápido?

Faça acontecer duas vezes com os mesmos passos e entradas, então remova tudo que não é necessário. Mire em 3–6 passos a partir de um estado limpo, com um registro reutilizável ou um corpo de requisição. Se não conseguir reduzir, isso costuma indicar dependência de volume de dados, timing ou jobs em background.

Devo começar chutando a causa ou reproduzindo primeiro?

Não mude nada ainda. Primeiro execute os passos do repórter exatamente e note o primeiro ponto onde sua experiência diverge (label de botão diferente, campo ausente, texto de erro diferente). Essa primeira discrepância é frequentemente a pista da condição real que dispara o bug.

Como posso rapidamente dizer se o bug está na UI, API ou banco de dados?

Verifique se os dados realmente mudaram. Se a API retorna o valor novo, mas a UI mostra o antigo, é provavelmente estado da UI, cache ou re-fetch. Se a resposta da API está errada ou o save não ocorre, foque em API ou BD. Se a linha do BD não atualiza (ou atualiza zero linhas), o problema está na persistência ou nas condições da query.

Que evidências devo capturar enquanto reproduzo o bug?

Confirme que uma requisição de rede é feita ao clicar e inspecione o payload da requisição e o corpo da resposta, não apenas o código de status. Capture um timestamp (com fuso horário) e um identificador de usuário para cruzar com os logs. Um 200 “sucesso” com um corpo inesperado pode ser tão importante quanto um 400/500.

Qual a melhor forma de testar bugs que “acontecem às vezes”?

Altere apenas uma coisa por vez: papel do usuário, registro (novo vs legado), navegador/dispositivo, sessão limpa (janela anônima/limpeza de cache) e rede. Testes de variável única mostram qual condição importa e evitam que você persiga coincidências causadas por múltiplas mudanças simultâneas.

Quais são os erros mais comuns que fazem perder tempo durante a depuração?

Mudar várias variáveis ao mesmo tempo, testar em outro ambiente que não o do repórter e ignorar permissões/roles são os maiores desperdiçadores de tempo. Outro erro comum é consertar o sintoma na UI enquanto um erro de validação na API/BD continua ocorrendo por baixo. Sempre rode o repro exato depois da sua mudança e então teste um cenário próximo.

O que significa “concluído” para uma correção, além de “funciona na minha máquina”?

“Done” significa: o repro mínimo original agora passa, e você re-testou um fluxo próximo que poderia ser impactado. Mantenha a checagem concreta, como um sinal visível de sucesso, resposta HTTP correta ou mudança esperada na linha do BD. Evite “acho que consertei” sem rodar os mesmos inputs na mesma baseline.

Como devo pedir a um builder de IA (ou colega) uma correção pequena e testável?

Forneça um arquivo de caso enxuto: passos mínimos com inputs exatos, ambiente/build/flags, conta e role de teste, esperado vs real e um trecho de prova (requisição/resposta, texto de erro ou trecho de log com timestamp). Peça o menor patch que faça o repro passar e inclua um mini plano de testes. Se usar Koder.ai, combinar esse arquivo com snapshots/rollback ajuda a testar pequenas mudanças com segurança e reverter se necessário.

Related posts