Testes em Go do zero: guia para desenvolvedor iniciante

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 testar em Go não é assustador, mas necessário

\n\n

Quando você escreve em Go pela primeira vez, parece que o compilador pega quase tudo: os tipos são rigorosos, os erros são explícitos, nil está sob controle. Mas quando seu projeto cresce para mais de 500 linhas, você percebe: sem testes não dá para viver. Uma alteração em um lugar quebra outro, e você só descobre isso em produção.

\n\n

Neste artigo, mostrarei por onde começar a testar em Go para um desenvolvedor iniciante. Vamos abordar testes unitários, testes tabelados, mocks e cobertura de código. Sem enrolação — apenas exemplos práticos e dicas úteis.

\n\n

Se você escreve em Go há pelo menos alguns meses, este material economizará horas de depuração.

\n\n

O que você precisa saber antes de começar

\n\n

Go fornece o pacote nativo testing — não é necessário instalar nada adicional. Os testes são escritos em arquivos com o sufixo _test.go e executados com o comando:

\n\n
go test ./...
\n\n

Regras básicas:

\n
    \n
  • A função de teste deve ser chamada TestXxx(t *testing.T), onde Xxx é o nome da função testada com letra maiúscula.
  • \n
  • Os arquivos de teste ficam junto ao código testado.
  • \n
  • Erros são reportados via t.Error() ou t.Fatal().
  • \n
\n\n

Vamos direto à prática.

\n\n

Escrevendo o primeiro teste unitário em Go

\n\n

Suponha que temos uma função simples que soma dois números:

\n\n
// calc.go\npackage calc\n\nfunc Sum(a, b int) int {\n    return a + b\n}
\n\n

Criamos o arquivo calc_test.go na mesma pasta:

\n\n
// calc_test.go\npackage calc\n\nimport "testing"\n\nfunc TestSum(t *testing.T) {\n    result := Sum(2, 3)\n    expected := 5\n\n    if result != expected {\n        t.Errorf("Sum(2,3) = %d; want %d", result, expected)\n    }\n}
\n\n

Executamos o teste:

\n\n
go test -v
\n\n

Você verá um PASS verde — sua primeira vitória nos testes. Observe: usamos t.Errorf (não fatal) — o teste continua mesmo se um caso falhar.

\n\n

Testes tabelados: quando um único teste não é suficiente

\n\n

Imagine que você precisa testar uma função com dezenas de entradas diferentes. Escrever 10 testes separados? Não, em Go existe o teste tabelado (table-driven test). É o padrão da comunidade Go.

\n\n

Vamos adicionar uma função de divisão ao nosso calc.go:

\n\n
func Divide(a, b int) (int, error) {\n    if b == 0 {\n        return 0, errors.New("division by zero")\n    }\n    return a / b, nil\n}
\n\n

Agora escrevemos o teste tabelado:

\n\n
func TestDivide(t *testing.T) {\n    tests := []struct {\n        name     string\n        a, b     int\n        expected int\n        wantErr  bool\n    }{\n        {"positive", 10, 2, 5, false},\n        {"negative", -6, 3, -2, false},\n        {"zero division", 5, 0, 0, true},\n        {"same numbers", 7, 7, 1, false},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            got, err := Divide(tt.a, tt.b)\n            if tt.wantErr {\n                if err == nil {\n                    t.Error("expected error, got nil")\n                }\n                return\n            }\n            if err != nil {\n                t.Errorf("unexpected error: %v", err)\n            }\n            if got != tt.expected {\n                t.Errorf("Divide(%d,%d) = %d; want %d", tt.a, tt.b, got, tt.expected)\n            }\n        })\n    }\n}
\n\n

O que há de legal aqui:

\n
    \n
  • Cada caso é um subteste com nome. Se um falhar, os outros continuam.
  • \n
  • Fácil adicionar novos casos — basta incluir uma linha na struct.
  • \n
  • O código lê-se como uma especificação.
  • \n
\n\n

Execute com a flag -v — você verá os nomes de todos os subtestes. Muito útil na depuração.

\n\n

Testando

Blogs

Book Recommendations