Como medir a cobertura de testes em Go e não enlouquecer
\n\nVocê escreveu testes para sua aplicação Go. Sente-se um super-herói? Está certo nisso. Mas há um detalhe: quanto exatamente do código está coberto por testes? Sem a resposta para essa pergunta, sua confiança é apenas um palpite.
\n\nA pergunta "How to measure test coverage in Go" é uma das mais populares no Stack Overflow (dezenas de milhares de visualizações). E não é por acaso. Desenvolvedores querem não apenas escrever testes, mas entender o quão eficazes eles são. Neste tutorial, abordaremos todas as formas de medir a cobertura de testes em Go: desde comandos básicos até técnicas avançadas com perfis e relatórios HTML.
\n\nO que é cobertura de testes e por que medi-la?
\n\nCobertura de testes (test coverage) é uma métrica que mostra qual porcentagem do seu código-fonte é executada durante os testes. É expressa em porcentagem. 100% de cobertura nem sempre é o Santo Graal, mas vale a pena buscar índices elevados.
\n\nPor que isso é necessário?
\n- \n
- Controle de qualidade: você vê quais partes do código ficaram sem testes \n
- Confiança em refatorações: alta cobertura reduz o risco de quebrar algo \n
- Métricas de CI/CD: é possível configurar um limite de cobertura e não permitir código com baixa cobertura \n
- Documentação: testes são documentação viva, e a cobertura mostra o quão completa ela é \n
Pegadinha: cobertura ≠ qualidade dos testes
\nLembre-se: 100% de cobertura não garante a ausência de bugs. É possível escrever testes que apenas chamam funções, mas não verificam nada. Cobertura é uma métrica quantitativa. Qualidade dos testes é qualitativa. Use ambas as abordagens.
\n\nMedição básica: go test -cover
\n\nVamos começar pelo mais simples. Go tem suporte nativo a cobertura diretamente na ferramenta go test. Vamos criar um projeto simples e ver como funciona.
Crie o arquivo math.go:
package main\n\nfunc Add(a, b int) int {\n return a + b\n}\n\nfunc Subtract(a, b int) int {\n return a - b\n}\n\nfunc Multiply(a, b int) int {\n return a * b\n}\n\nfunc Divide(a, b int) (int, error) {\n if b == 0 {\n return 0, nil // Erro: deveria ser return 0, errors.New("division by zero")\n }\n return a / b, nil\n}\n\nE agora, o teste (math_test.go):
package main\n\nimport "testing"\n\nfunc TestAdd(t *testing.T) {\n result := Add(2, 3)\n if result != 5 {\n t.Errorf("expected 5, got %d", result)\n }\n}\n\nfunc TestSubtract(t *testing.T) {\n result := Subtract(10, 4)\n if result != 6 {\n t.Errorf("expected 6, got %d", result)\n }\n}\n\n// Intencionalmente não testamos Multiply e Divide\n\nAgora execute os testes com a flag -cover:
go test -cover\n\nA saída será algo como:
\n\nok example/math 0.002s coverage: 50.0% of statements\n\nCorreto — 50% do código está coberto, porque Multiply e Divide não são testados. Mas isso é apenas um número geral. E se quisermos ver um perfil detalhado de cobertura?
Perfil de cobertura: go test -coverprofile
\n\nA flag -coverprofile salva informações detalhadas sobre a cobertura em um arquivo:
go test -coverprofile=coverage.out\n\nAgora, na pasta, apareceu o arquivo coverage.out. Abra-o — é um formato de texto onde cada linha mostra se uma instrução específica do código foi executada. Mas lê-lo manualmente é entediante. Vamos para a visualização.
Relatório HTML: go tool cover -html
\n\nA forma mais conveniente de analisar a cobertura é o relatório HTML. Ele destaca o código executado em verde e o não executado em vermelho.
\n\ngo tool cove