Cache em Go: Inimigo dos Testes? Analisando o Force Retesting

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que o Go esconde os resultados dos testes? (E como isso atrapalha a vida)

\n\n

Imagine: você programa em Go, executa go test, vê a marca verde... mas algo deu errado. Você corrigiu um bug, executa os testes novamente — e vê verde de novo. E o bug continua lá! Familiar? Bem-vindo ao mundo do cache de testes do Go.

\n\n

Go é uma linguagem que adora velocidade. Para não executar os mesmos testes várias vezes, o compilador armazena os resultados em cache. Parece conveniente, até você se deparar com uma situação em que o cache de testes do Go começa a trabalhar contra você. Isso afeta especialmente desenvolvedores que trabalham com testes de integração, sistema de arquivos ou APIs externas.

\n\n

Neste artigo, analisaremos duas abordagens para resolver o problema: force retesting (reinicialização forçada) e a desativação completa do cache de testes. Você aprenderá quando usar cada uma e terá exemplos de código funcionais.

\n\n

Como funciona o cache de testes em Go

\n\n

Antes de quebrar, vamos entender como funciona. O Go armazena em cache os resultados dos testes com base em um hash de:

\n
    \n
  • Código-fonte (arquivos .go)
  • \n
  • Arquivos de teste
  • \n
  • Variáveis de ambiente
  • \n
  • Flags de compilação
  • \n
\n\n

Se nada mudou — o Go simplesmente mostra o resultado em cache. Rápido? Sim. Perigoso? Com certeza! Imagine que seu teste depende de tempo, números aleatórios ou um serviço externo. O cache dirá: "Está tudo ok!", embora na verdade o teste já teria falhado há muito tempo.

\n\n
// Exemplo de teste que ficará falso-verde devido ao cache\nfunc TestCurrentTime(t *testing.T) {\n    now := time.Now()\n    if now.Year() != 2024 {\n        t.Errorf("O ano deve ser 2024, obtido %d", now.Year())\n    }\n}
\n\n

Execute este teste uma vez — ele passará. Corrigiu o ano para 2025 no código? O cache ainda mostrará o resultado antigo. E você ficará se perguntando por que o CI falha, enquanto localmente tudo "funciona".

\n\n

Abordagem 1: Force retesting (reinicialização forçada)

\n\n

A forma mais popular de combater o cache é a flag -count=1. Isso é o force retesting em sua forma pura. Ele diz ao Go: "Não confie no cache, execute o teste novamente".

\n\n
// Execução com reinicialização forçada\ngo test -count=1 ./...
\n\n

Por que -count=1 e não -count=0? Porque -count define o número de execuções do teste. 1 é o valor mínimo que desativa o cache. 0 simplesmente não executará nada.

\n\n

Quando usar force retesting

\n
    \n
  • Testes de integração que acessam banco de dados ou API
  • \n
  • Testes com dados aleatórios (testes fuzz, geração de UUID)
  • \n
  • Testes dependentes de tempo (timeouts, datas)
  • \n
  • Desenvolvimento local, quando você altera o código com frequência
  • \n
\n\n

Exemplo: teste de integração com force retesting

\n\n
package db_test\n\nimport (\n    "testing"\n    "time"\n)\n\nfunc TestDatabaseConnection(t *testing.T) {\n    // Este teste depende de um servidor ativo\n    // Sem -count=1 ele pode mostrar um resultado antigo\n    db := connectToDatabase()\n    if err := db.Ping(); err != nil {\n        t.Fatalf("Não foi possível conectar: %v", err)\n    }\n    \n    // Simulação de atraso temporário\n    time.Sleep(100 * time.Millisecond)\n    if err := db.Query("SELECT 1"); err != nil {\n        t.Errorf("Consulta não executada: %v", err)\n    }\n}
\n\n

Execute: go test -count=1 -v ./db/. Agora cada execução é honesta. Mas há um detalhe: o force retesting não resolve o problema globalmente. Se você esquecer a flag — o cache voltará.

\n\n

Abordagem 2: Desativação completa do cache de testes

\n\n

A segunda opção é radical. Você simplesmente diz ao Go: "Não armazene nada em cache". Isso é feito através da variável de ambiente GOCACHE=off ou da flag -count=1

Blogs

Book Recommendations