Ao escrever testes unitários em Go — especialmente testes orientados a tabelas (table-driven tests) —, funções que escrevem no pacote global padrão log podem rapidamente poluir o seu terminal.
Se você tiver uma dúzia de casos de teste e apenas um falhar, ainda precisará rolar a tela pelos logs de todos os casos bem-sucedidos só para encontrar o erro. Esse ruído atrasa a depuração e torna a saída dos seus testes difícil de ler.
Vamos analisar um cenário comum e ver como corrigi-lo capturando os logs e imprimindo-os apenas quando um teste falhar.
Digamos que temos uma função simples que registra suas entradas e seu resultado final no log:
package add
import (
"log"
)
func add(x, y int) int {
log.Printf("add %d %d", x, y)
res := x + y
log.Printf("add %d %d = %d", x, y, res)
return res
}
Agora, escrevemos um teste unitário padrão orientado a tabela com três casos (onde o último foi intencionalmente projetado para falhar):
package add
import (
"testing"
)
func TestAdd(t *testing.T) {
inputs := []struct {
x int
y int
want int
}{
{x: 1, y: 2, want: 3},
{x: 3, y: 2, want: 5},
{x: 4, y: 5, want: 0}, // Intentionally failing case
}
for _, in := range inputs {
got := add(in.x, in.y)
if in.want != got {
t.Errorf("add %d %d got %d want %d", in.x, in.y, got, in.want)
}
}
}
Quando executamos go test, a saída contém os logs de todas as entradas que passaram antes de finalmente nos mostrar a falha:
$ go test
2020/09/05 09:01:25 add 1 2
2020/09/05 09:01:25 add 1 2 = 3
2020/09/05 09:01:25 add 3 2
2020/09/05 09:01:25 add 3 2 = 5
2020/09/05 09:01:25 add 4 5
2020/09/05 09:01:25 add 4 5 = 9
--- FAIL: TestAdd (0.00s)
add_test.go:28: add 4 5 got 9 want 0
FAIL
exit status 1
Seria muito melhor ver apenas os logs gerados pelas entradas que falharam. Podemos alcançar isso passando um logger para a nossa função (Injeção de Dependência) e gravando os logs em um buffer temporário durante os testes.
Primeiro, vamos atualizar nossa função para aceitar um *log.Logger:
package add
import "log"
func add(logger *log.Logger, x, y int) int {
logger.Printf("add %d %d", x, y)
res := x + y
logger.Printf("add %d %d = %d", x, y, res)
return res
}
Em seguida, atualizamos nosso teste. Para cada iteração de caso de teste, criaremos um novo bytes.Buffer e conectaremos um novo logger a ele. Se o teste passar, o buffer é simplesmente descartado. Se o teste falhar, imprimimos o conteúdo do buffer junto com a mensagem de erro!
(Nota: Também estamos atualizando o teste para usar t.Run, que é a maneira idiomática de executar subtestes orientados a tabelas em Go).
package add
import (
"bytes"
"log"
"testing"
)
func TestAdd(t *testing.T) {
inputs := []struct {
name string
x int
y int
want int
}{
{name: "1+2", x: 1, y: 2, want: 3},
{name: "3+2", x: 3, y: 2, want: 5},
{name: "4+5", x: 4, y: 5, want: 0}, // Intentionally failing case
}
for _, in := range inputs {
t.Run(in.name, func(t *testing.T) {
// 1. Create a buffer to capture the logs
var buf bytes.Buffer
// 2. Create a new logger that writes to the buffer
logger := log.New(&buf, "", log.LstdFlags)
// 3. Pass the custom logger into our function
got := add(logger, in.x, in.y)
if in.want != got {
// 4. Print the buffer contents ONLY if the test fails
t.Errorf("got %d want %d\n\nExecution Logs:\n%s", got, in.want, buf.String())
}
})
}
}
Agora, quando executamos nossos testes, a saída fica perfeitamente limpa e altamente acionável. Vemos apenas os logs relevantes para a falha:
$ go test
--- FAIL: TestAdd (0.00s)
--- FAIL: TestAdd/4+5 (0.00s)
add_test.go:35: got 9 want 0
Execution Logs:
2020/09/05 09:22:48 add 4 5
2020/09/05 09:22:48 add 4 5 = 9
FAIL
exit status 1
Ao desacoplar nossas funções do logger global, tornamos nosso código mais flexível, nossas suítes de teste mais silenciosas e nosso processo de depuração significativamente mais rápido.
Baixe a edição offline selecionada de O Estilo de Vida do Kaue—um guia prático para otimizar 🍏 Saúde, 💰 Riqueza, ❤️ Amor e 🧘 Sentido.
Receba notificações quando eu publicar novos ensaios, resumos de livros e guias práticos sobre como viver bem. Sem spam—cancele quando quiser.
Tem alguma pergunta, perspectiva ou sugestão? Compartilhe suas ideias abaixo. Os comentários usam o GitHub Discussions (sem anúncios e sem spam)—clique em Entrar com o GitHub abaixo para comentar ou reagir (criar uma conta gratuita no GitHub leva menos de um minuto).
Atualizado em 11 de out. de 2026.
AVISO LEGAL: O conteúdo deste site tem finalidade exclusivamente informativa e educacional e não constitui aconselhamento médico, psicológico, financeiro, de investimentos, tributário ou jurídico. As ideias, a curadoria e as opiniões aqui apresentadas são exclusivamente minhas e não representam as do meu empregador. Os resumos de livros, palestras e artigos são comentários educacionais independentes e permanecem propriedade intelectual de seus respectivos autores. Ferramentas de IA podem ser utilizadas para auxiliar na edição, formatação e síntese; embora todos os esforços sejam feitos para garantir a precisão, erros podem ocorrer. PRIVACIDADE: Este site utiliza serviços de terceiros para inscrição opcional em newsletter (follow.it), comentários (giscus / GitHub Discussions) e mídia incorporada (YouTube), que podem processar endereços IP e cookies dos visitantes de acordo com suas respectivas políticas de privacidade.