Cultura de Testes em Go: Simples, Rápido, Orientado por Tabela
Go trata testes como código comum no mesmo módulo, compilado pela mesma toolchain e executado com um único comando.
Busque em todas as páginas da documentação
Go trata testes como código comum no mesmo módulo, compilado pela mesma toolchain e executado com um único comando.
Esse design incentiva equipes a adotarem testes pequenos, rápidos e legíveis em vez de frameworks pesados.
testing embutido do Go, juntamente com go test, é a camada de qualidade padrão - sem florestas XML estilo JUnit, sem bibliotecas de asserção obrigatórias e sem um processo de teste separado para configurar.TestXxx, BenchmarkXxx, ExampleXxx, FuzzXxx, testes orientados por tabela, subtestes t.Run, -race, perfis de cobertura.Go distribui um único vocabulário de testes na biblioteca padrão.
Você nomeia funções TestSomething(t *testing.T), as coloca em something_test.go ao lado de something.go, e executa go test.
O compilador constrói um binário de teste que vincula seu pacote mais os arquivos de teste; go test o executa e reporta sucesso/falha.
Não há arquivo de configuração global necessário para a maioria dos pacotes.
Simples significa que os leitores veem o fluxo arrange-act-assert em Go puro.
Uma asserção falha geralmente é if got != want { t.Fatalf(...) } ou um helper simples - não um DSL com vinte matchers.
Rápido é uma expectativa cultural apoiada por ferramentas.
go test armazena em cache resultados de pacotes bem-sucedidos com base nas entradas; pacotes inalterados pulam a reexecução.
Equipes visam testes de pacotes sub-segundo para que go test ./... seja executado a cada commit.
Orientado por tabela é a maneira idiomática de adicionar casos sem copiar e colar funções de teste.
Uma slice de structs contém name, entradas e saídas esperadas; um loop chama t.Run por linha.
A tabela é a especificação; o loop é o harness.
production.go *_test.go
| |
+-------- mesmo pacote -+
|
go test ./...
|
passa / falha por pacote
Modos de Pacote: go test pode executar testes no pacote em teste (package foo) ou como um pacote de teste externo (package foo_test) para exercitar apenas APIs exportadas.
Ambos compilam com o mesmo comando; a escolha sinaliza a intenção aos consumidores.
Subtestes (t.Run) fornecem nomes hierárquicos na saída e permitem execução paralela com t.Parallel() dentro de um loop de tabela.
Falhas identificam o nome do caso (TestParse/empty_input) em vez de um número de linha em um teste monolítico.
Exemplos são testes que também aparecem na documentação.
O comentário // Output: de uma função Example é verificado por go test, mantendo o godoc honesto.
Benchmarks medem ns/op e alocações; fuzz tests (testes de fuzzing) mutam entradas para encontrar crashes.
Todos os três usam a mesma nomenclatura de arquivo e ponto de entrada go test com assinaturas de função diferentes.
Detector de corrida (go test -race) instrumenta o acesso à memória para capturar data races que passam sob agendamento normal.
É mais lento e pertence à CI ou ao pre-push, não a cada salvamento.
func TestAdd(t *testing.T) {
tests := []struct{ a, b, want int }{{1, 2, 3}}
for _, tc := range tests {
t.Run("", func(t *testing.T) {
if got := Add(tc.a, tc.b); got != tc.want {
t.Fatalf("got %d want %d", got, tc.want)
}
})
}
}Bibliotecas de terceiros como testify adicionam asserções e mocks; httptest de net/http/httptest é da stdlib para testes de handlers.
Equipes frequentemente adotam testify para ergonomia, mas mantêm a estrutura orientada por tabela e go test como o runner.
| Prática | Força | Fraqueza | Melhor ajuste |
|---|---|---|---|
| Testes puros da stdlib | Zero dependências, sempre compila | Comparações verbosas | Bibliotecas, OSS |
| Asserções testify | Falhas legíveis | Módulo extra | Grandes equipes de aplicativos |
| Testes de integração pesados de DB | Captura bugs reais de SQL | CI lenta, instável sem containers | Poucos caminhos de smoke test |
| Fuzz + race em CI | Encontra crashes e races | Custo de CPU e tempo | Parsers sensíveis à segurança |
Pirâmide de testes para serviços Go: muitos testes rápidos em funções puras e handlers com httptest; menos testes acessando bancos de dados reais com testcontainers; end-to-end fora de go test ou em um job noturno.
Monorepos: go test ./... na raiz do módulo ou workspace respeita go.work; acertos de cache escalam com pacotes inalterados.
Genéricos e orientados por tabela: parâmetros de tipo não mudam o padrão - tabelas podem conter entradas tipadas; subtestes ainda nomeiam casos.
Portões de cobertura: go test -coverprofile alimenta go tool cover e limiares de CI; alta porcentagem sem asserções significativas é um antipadrão conhecido.
pprof explica onde o tempo é gasto em produção.A co-localização mantém os exemplos precisos quando as APIs mudam.
go test compila ambos juntos, então os testes quebram em tempo de compilação quando as assinaturas se movem.
Testes unitários em nível de pacote geralmente devem terminar em milissegundos a poucos segundos.
Se go test ./... exceder alguns minutos, divida suítes de integração ou use build tags.
Não, mas é idiomático para funções com múltiplos pares de entrada/saída.
Testes de caminho único podem permanecer como uma função plana sem uma tabela.
Execuções bem-sucedidas armazenam resultados em cache por hash do pacote.
Use go test -count=1 para desativar o cache ao depurar testes instáveis.
package foo_test importa foo como um consumidor faria - bom para contratos de API.
package foo pode testar helpers não exportados.
Prefira interfaces pequenas no código de produção e fakes escritos à mão em _test.go.
Geradores de mock pesados são opcionais, não padrão.
Exemplos são executados sob go test e renderizados em pkg.go.dev quando incluem comentários // Output:.
Eles documentam o uso da API pública, não casos de borda exaustivos.
Em jobs dedicados ou noturnos, não em cada PR, a menos que comparando com uma linha de base armazenada.
Benchmarks são barulhentos em runners compartilhados.
Não. Fuzzing explora entradas inesperadas; tabelas documentam o comportamento esperado que os revisores podem ler.
Linters pegam problemas estáticos; testes pegam comportamento.
A CI deve executar ambos - veja os portões de qualidade de linting para ordenação.
Sleep torna os testes lentos e instáveis sob carga.
Use canais, sync.WaitGroup, ou controle de resposta httptest em vez disso.
Geralmente não - testes pertencem ao mesmo módulo que o código que eles exercitam.
Módulos e2e separados são para testes de implantação black-box.
Versões de Stack: Esta página foi escrita para Go 1.26.x (GC padrão Green Tea, go fix modernizers - verifique o patch na compilação), chi (última versão - verifique na compilação), gin (última versão - verifique na compilação), echo (última versão - verifique na compilação), google.golang.org/grpc (última versão - verifique na compilação), sigs.k8s.io/controller-runtime (última versão - verifique na compilação), kubebuilder (última versão - verifique na compilação), tinygo (última versão - verifique os alvos de placa na compilação), wazero (última versão - verifique na compilação) e golangci-lint (última versão - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026