Como o go test executa todos os testes do projeto: análise por baixo dos panos

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

Como executar todos os testes em um projeto Go e o que acontece "por baixo dos panos"?

\n

Todo desenvolvedor Go já digitou pelo menos uma vez no terminal o comando mágico go test ./... e observou as marcas verdes correndo pela tela. Mas você já parou para pensar no que realmente acontece nesse momento? Por que os testes são executados exatamente dessa forma e não de outra? E por que, às vezes, o go test silenciosamente ignora seus novos testes?

\n

Neste artigo, não vamos apenas responder a uma pergunta popular do Stack Overflow (onde ela acumulou milhares de visualizações), mas vamos olhar por baixo dos panos do compilador Go e descobrir como o mecanismo de testes funciona. Vamos nessa!

\n\n

Por que go test ./... é mágico?

\n

Vamos começar pelo básico. O comando go test sem argumentos executa testes apenas no pacote atual. Mas se você tem um projeto com dezenas de pacotes (e em produção real é assim), percorrê-los manualmente é como uma tortura medieval. É aí que entra o ./....

\n

Esse padrão significa: "encontre todos os pacotes recursivamente, a partir do diretório atual". O Go percorre a árvore de diretórios, ignorando vendor e módulos, e coleta uma lista de todos os pacotes. Para cada um deles, ele executa uma instância separada do go test.

\n

Mas e se você quiser executar testes apenas em diretórios específicos? Por exemplo, apenas em ./internal/...? Funciona da mesma forma: go test ./internal/....

\n

Importante: se você usa Go Modules (e a partir do Go 1.16+ isso é padrão), o ./... funciona apenas dentro do módulo atual. Para testar todos os módulos em um workspace, você precisará usar go test ./... em cada um deles ou configurar o go.work.

\n\n

O que é um "pacote" no contexto do go test?

\n

O Go opera com o conceito de pacote — um grupo de arquivos .go em um mesmo diretório. Arquivos de teste (com o sufixo _test.go) também são considerados parte do pacote, mas são compilados separadamente. Quando você executa go test, o Go compila um binário de teste que inclui:

\n
    \n
  • O código-fonte do pacote (mas apenas o que é usado nos testes)
  • \n
  • O código dos próprios testes
  • \n
  • Uma estrutura de runtime especial para execução e relatório
  • \n
\n

Esse binário é executado, realiza os testes e exibe o resultado. Todo o processo é separado para cada pacote.

\n\n

Como o Go decide quais testes executar?

\n

Quando você digita go test ./..., o Go executa as seguintes etapas:

\n
    \n
  1. Varredura do sistema de arquivos — o Go encontra todos os diretórios que contêm arquivos .go.
  2. \n
  3. Filtragem — são ignorados os diretórios vendor, testdata e pastas ocultas (que começam com .).
  4. \n
  5. Compilação — para cada pacote, é criado um binário temporário.
  6. \n
  7. Execução — o binário é executado e os resultados são coletados.
  8. \n
  9. Cache — se o código não mudou, o Go usa o cache e exibe (cached).
  10. \n
\n

O último ponto é uma causa frequente de surpresa. Você alterou o teste, executa go test ./..., e ele diz "ok (cached)". Por quê? Porque o Go armazena em cache os resultados com base no hash dos arquivos de entrada. Se você alterou apenas um comentário ou uma importação não utilizada, o hash não muda e o teste não é reexecutado.

\n

Dica: para forçar a limpeza do cache, use o comando go clean -testcache. Ou use a flag -count=1, que faz o Go ignorar o cache: go test -count=1 ./....

\n\n

Paralelismo: por que os testes nem sempre são mais rápidos?

\n

Por padrão, o go test executa testes dentro de um mesmo pacote sequencialmente. Mas entre pacotes — em paralelo! O número de pacotes simultâneos é determinado pela flag -p (por padrão, igual ao número de CPUs).

\n

Isso parece ótimo, mas há um detalhe: e

Blogs

Book Recommendations