Home Projetos & Releases BigBangcraft Blog Sobre & Carreira
Ruby on Rails • Hub 6 min de leitura 10 visualizações
Raw .md

A miopia de validar o bug no Rails antes de auditar as premissas da factory

PD

Pedro Dalben

CTO no Integrar Plus • Publicado em 30 de October de 2026

A miopia de validar o bug no Rails antes de auditar as premissas da factory

Um teste que passa sem falhar antes da alteração do código não prova nada. Quase todo desenvolvedor Rails já ouviu essa máxima, mas ela esconde uma armadilha ainda mais perigosa: o teste que falha no branch principal pelo motivo errado e depois passa no seu branch de correção por pura coincidência.

Essa contradição apareceu com força recente na discussão sobre a correção aberta no código público do Forem, a plataforma que roda a comunidade DEV. Um desenvolvedor externo encontrou uma falha antiga de concessão de emblemas, enviou um ajuste e viu sua suíte passar com louvor. Na revisão de código, porém, descobriu-se que o teste original estava verde porque a factory usada no cenário mascarava o comportamento do serviço. O teste verificava apenas o saldo final de registros na tabela, sem enxergar que a lógica interna continuava tentando processar duplicatas e falhando silenciosamente em outra camada.

O debate gerou duas posturas claras nos bastidores. De um lado, há quem defenda que a disciplina do teste de regressão se resume a rodar a asserção contra o branch principal sem o patch aplicado, o famoso teste de bancada com git stash. A lógica dessa corrente é simples: se a suíte quebrar na versão limpa e passar na versão com o seu código, a correção estaria provada. De outro lado, engenheiros mais céticos apontam que essa abordagem é ingênua quando trabalhamos com fixtures complexas. Para esse segundo grupo, a prioridade técnica deve ser fechar deliberadamente todas as rotas de escape do cenário de teste, removendo atributos padrões ou flags que permitiriam ao ActiveRecord disfarçar uma falha de validação como se fosse o comportamento esperado do serviço.

Eu tendo a concordar com o segundo grupo, mas com uma ressalva operacional severa. A checagem com git stash é útil, só que ela testa apenas a diferença entre dois estados do repositório, não a aderência do seu teste à realidade de produção. No Rails, onde callbacks, valores default de banco de dados e validações de unicidade interagem nos bastidores, um teste pode facilmente falhar no branch principal por causa de uma colisão de índice e passar na sua branch porque você alterou um parâmetro irrelevante. Você acha que consertou o algoritmo, mas só contornou a validação que estava gritando no log.

Quando você usa FactoryBot ou fixtures sem prestar atenção nos valores definidos por padrão, o ambiente de teste vira uma versão higienizada e irreal do seu banco PostgreSQL. Se a factory define que um emblema não aceita múltiplas concessões, e a sua asserção apenas verifica se o total de registros não aumentou, você não está testando a regra de negócio do seu serviço. Você está apenas testando se o ActiveRecord barrou o registro duplicado na linha defensiva da validação. O serviço continuou gastando ciclos de CPU, montando queries desnecessárias e disparando callbacks que deveriam ter sido abortados na primeira linha da rotina.

Para evitar essa armadilha no dia a dia, existem três práticas de engenharia que mudam a qualidade dos testes de regressão em ecossistemas Rails.

A primeira é eliminar asserções puramente numéricas sobre tabelas finais. Verificar se a contagem de uma tabela subiu ou permaneceu estável é o tipo mais frágil de asserção que existe. Em vez de confiar em um contador global, o teste precisa verificar o retorno explícito do objeto de serviço ou inspecionar se a transação chegou a executar etapas secundárias, como o enfileiramento de um job ou o envio de uma notificação. Se o seu serviço de concessão de emblemas falha na verificação de elegibilidade, ele não deve sequer tentar instanciar o modelo de persistência.

A segunda prática é criar cenários propositalmente hostis na montagem dos dados. Se o bug que você está investigando envolve a concessão indevida de itens duplicados, a sua fixture precisa ter a flag de múltiplos itens explicitamente ativada no teste. Ao remover o impedimento estrutural do modelo, você força o teste a depender exclusivamente da lógica do código que você acabou de escrever. Se o teste continuar verde apenas quando a regra do modelo está ligada, a sua correção não fez diferença alguma.

A terceira prática diz respeito ao monitoramento de ruído no log de testes. Muitas vezes o Rails engole erros de unicidade ou emite avisos de depreciação e alertas de validação que passam batidos enquanto os pontinhos verdes avançam no terminal. Em qualquer sistema em produção, uma exceção capturada que gera um aviso no log a cada dez minutos perde o sentido e vira ruído de fundo. Um teste de regressão decente deve falhar se uma mensagem de aviso inesperada for registrada durante a execução daquele bloco específico.

Construir software sustentável em cima de frameworks produtivos como o Rails exige desconfiar da própria facilidade da ferramenta. O ActiveRecord facilita tanto a persistência que nos desacostuma a acompanhar o ciclo de vida completo dos objetos na memória. Quando escrevemos um teste a partir da nossa suposição preliminar do problema, quase sempre desenhamos o cenário para confirmar o nosso viés. O resultado é um teste que passa no terminal local, passa na integração contínua e falha no servidor assim que o primeiro usuário real faz uma requisição fora do roteiro ideal da factory.

A maturidade de uma equipe não é medida pela quantidade de testes que ficam verdes na pipeline, mas pela capacidade técnica de construir testes que realmente teriam pegado o problema se tivessem sido escritos seis meses antes. Antes de comemorar um diff verde no repositório, gaste dez minutos tentando quebrar a sua própria suposição. Force o seu código a falhar pelas vias normais e garanta que ele não está se escorando em comportamentos acidentais da infraestrutura de teste.

Fontes

PD

Sobre Pedro Dalben

CTO e arquiteto full stack especializado em Ruby on Rails, Vue.js, sistemas multi-tenant e infraestrutura distribuída.