
“Cannot reproduce” [não é possível reproduzir] é a forma mais comum de um relatório de bug morrer, e vale a pena ler essa frase com atenção, porque ela não diz o que as pessoas pensam que diz. Não é uma afirmação sobre o bug. É uma afirmação sobre dois ambientes: o deles, onde aconteceu, e o seu, onde não aconteceu.
O bug não está em dúvida. Alguém viu acontecer. O que está em dúvida é se você consegue reconstruir as condições que ele exigiu, e na maior parte das vezes o relatório não as contém, porque quem escreveu não tinha ideia de qual, entre as mil coisas ao redor, era a que importava.
O que uma reprodução realmente exige
Passos são apenas uma de quatro coisas, e são a única em que todo mundo pensa.
Os mesmos passos. O que a pessoa clicou, na ordem certa, partindo de um ponto de onde você também consegue partir.
O mesmo estado. A conta, as permissões, as feature flags, as configurações alteradas há dezoito meses, o rascunho pela metade parado no banco de dados. É esse o item que mais derruba as tentativas, porque o estado é invisível para quem está dentro dele. A pessoa não sabe que a conta dela é fora do comum. Para ela, é só a conta dela.
Os mesmos dados. Não um registro de teste recém-criado, mas o específico: o pedido com um reembolso, o nome com apóstrofo, a lista vazia, o upload de quarenta megabytes. Dados de seed são organizados. Dados de produção são quinze anos de decisões, o que é a mesma lacuna que faz o staging mentir para você.
O mesmo ambiente. Navegador e build, dispositivo, rede, tamanho de tela, relógio, extensões. A versão sozinha já pode bastar: “latest Chrome” foram três versões principais diferentes em uma semana.
São quatro eixos, e um relatório normalmente fixa apenas um deles. O trabalho de reproduzir é adivinhar os outros três, e é por isso que leva uma tarde inteira e por isso que tantas vezes termina em um dar de ombros.
Comece pelo estado, não pelos passos
O instinto é seguir os passos e ver o que acontece. O melhor primeiro movimento é perguntar o que precisaria ser verdade para que esses passos falhassem.
Se o checkout quebra na etapa de pagamento, os passos são três cliques que qualquer pessoa consegue dar. O que não é universal é o carrinho, o endereço, o método de pagamento, a moeda, se essa conta já recebeu algum reembolso. Descubra quais desses fatores poderiam mudar o resultado, e você transformou um relatório vago em três ou quatro experimentos específicos.
- Fraco
- Seguiu os passos em uma conta de teste. Funciona normalmente. Fechado como "cannot reproduce".
- Melhor
- Os passos funcionam em uma conta nova. A conta de quem relatou tem um cartão salvo em uma moeda que deixamos de suportar, e a falha está na consulta de moeda. Reproduzido adicionando um cartão assim a uma conta de teste.
A segunda versão não exige mais esforço. É o mesmo esforço apontado para a pergunta certa.
Reduza a reprodução até a menor coisa que ainda falha
Assim que a falha acontecer de forma confiável, comece a remover partes. Remova um passo, remova um campo, use um arquivo menor, desative uma extensão, reduza os dados. Cada remoção ou mantém a falha, e nesse caso aquela parte não era necessária, ou interrompe a falha, e nesse caso você acabou de encontrar algo que importa.
Vale a pena fazer isso mesmo quando você já tem a correção, por dois motivos. Uma reprodução mínima é um caso de teste que alguém pode guardar. E o próprio ato de reduzir muitas vezes encontra a causa antes mesmo de você olhar para qualquer código: o bug que só sobrevive quando a lista está vazia já está dizendo o que ele é.
Fique atento à reprodução que funciona só às vezes. Isso não é uma reprodução malsucedida, é um formato diferente de bug, e a intermitência é dado, não ruído: alguma coisa está em uma corrida de threads, ou depende de ordem, ou de um cache estar frio. A mesma lógica que faz um teste instável valer a pena investigar em vez de simplesmente rodar de novo se aplica aqui.
Os que você não consegue reproduzir por construção
Algumas falhas não podem ser reconstruídas na sua máquina, e nenhuma dose de persistência muda isso. Reconhecê-las cedo vale mais do que insistir mais.
Precisava do relógio deles. Um dispositivo com a hora errada gera falhas de certificado, sessões expiradas e timestamps impossíveis. Essas foram três das cinco causas por trás de um aviso de certificado.
Precisava da rede deles. Um proxy corporativo, um filtro de DNS, um portal cativo, uma operadora móvel que reescreve requisições. Você não consegue entrar nessa rede, então não consegue ver o que ela faz.
Precisava do build deles. Um lançamento em fases colocou uma fração dos usuários em uma versão que mais ninguém tem, inclusive você.
Precisava do momento. Um deploy pela metade, um cache que estava frio, um serviço de terceiros que ficou lento por noventa segundos. O estado que causou o problema deixou de existir antes de o relatório ser escrito.
Precisava das extensões deles. Algo injetado na página a alterou. Você tem extensões diferentes, então tem uma página diferente.
Nesses casos a pergunta não é “como eu reproduzo isso”, e sim “o que era verdade naquele momento, e eu ainda consigo descobrir?”
O que é um argumento a favor de capturar em vez de reproduzir
Cada item dessa lista é invisível depois do fato e barato de registrar no momento em que acontece. O console no instante em que quebrou. A requisição que falhou, com seu status e seu tempo. O build do navegador, o tamanho da tela, a URL. Nada disso exige que quem relata saiba o que importa, e essa é justamente a dificuldade toda, porque a pessoa nunca sabe.
Esse é o argumento a favor de um relatório que carrega sua própria evidência, em vez de uma descrição dela. Reproduzir é uma forma de recuperar informação que foi descartada, e é caro justamente porque a informação foi descartada.
Session Replay
Extensão gratuita para Chrome. Um clique na página que está com problema captura a tela, o console e o log de rede, e entrega um link para você colar no chamado.
Perguntando de novo para quem relatou, da forma certa
Quando você realmente precisar voltar a perguntar, peça as coisas que a pessoa consegue responder de fato, não as que você gostaria que ela tivesse escrito.
Ruim: “por favor, forneça os passos exatos para reproduzir.” A pessoa já acredita que fez isso.
Melhor, e cada uma dessas perguntas tem uma boa taxa de acerto:
- A que horas aconteceu, e que horas o seu dispositivo está marcando agora? São duas perguntas, não uma. A diferença entre elas já é um diagnóstico.
- Aconteceu mais de uma vez? Uma vez é um momento. Repetidamente é um estado.
- Acontece em uma rede diferente, por exemplo dados móveis em vez de wifi?
- O que exatamente está na tela? As palavras, não um resumo delas.
- Com quem mais você consegue reproduzir isso? Outra conta reduz a busca para os dados; outra pessoa na mesma conta reduz a busca para o dispositivo.
O guia de relatório de bugs mostra o formato completo de um bom relatório, e os erros mais comuns cobre o que costuma faltar com mais frequência.
O que escrever quando você desiste
Às vezes você realmente não consegue, e fechar o chamado é a decisão certa. Não feche como “cannot reproduce” e mais nada, porque essa frase não diz nada para a próxima pessoa, que vai gastar a mesma tarde que você gastou.
Escreva o que você tentou. Qual conta, qual navegador e build, quais dados, quais dos quatro eixos você variou e quais não conseguiu variar. Assim, o próximo relatório do mesmo problema, vindo de outra pessoa com outro detalhe, não é um recomeço do zero. É o segundo ponto de dados, e dois relatórios que compartilham uma coisa fora do comum costumam ser a resposta inteira.
Essa também é a versão honesta do status. O bug não foi refutado. Ele não foi reproduzido com a informação disponível, o que é uma afirmação diferente e bem mais útil de deixar registrada.