Médio Go

Helper com t.Helper para verificar strings

Enunciado

Implemente uma função Contem(frase, palavra string) bool que verifica se palavra aparece em frase. Escreva um helper verificaContem(t *testing.T, frase, palavra string, esperado bool) marcado com t.Helper() e use-o em um teste table-driven com t.Run.

Requisitos

  • Contem deve retornar true se palavra for substring de frase.
  • O helper deve chamar t.Helper() na primeira linha.
  • O teste deve ser table-driven com pelo menos quatro casos, incluindo um false.
  • Cada caso deve rodar dentro de t.Run.

Código inicial

package textos

import (
	"strings"
	"testing"
)

func Contem(frase, palavra string) bool {
	return strings.Contains(frase, palavra)
}

func verificaContem(t *testing.T, frase, palavra string, esperado bool) {
	// implemente com t.Helper()
}

func TestContem(t *testing.T) {
	// implemente
}

Saída esperada

=== RUN   TestContem
=== RUN   TestContem/palavra_presente
=== RUN   TestContem/palavra_ausente
=== RUN   TestContem/case_sensitive
=== RUN   TestContem/string_vazia
--- PASS: TestContem (0.00s)
    --- PASS: TestContem/palavra_presente (0.00s)
    --- PASS: TestContem/palavra_ausente (0.00s)
    --- PASS: TestContem/case_sensitive (0.00s)
    --- PASS: TestContem/string_vazia (0.00s)
PASS
ok  	textos	0.002s
Ver dica

Dentro do helper, chame t.Helper() antes de qualquer verificação. Use t.Errorf para reportar a falha com contexto.

Mostrar solução
package textos

import (
	"strings"
	"testing"
)

// Contem informa se palavra é substring de frase.
func Contem(frase, palavra string) bool {
	return strings.Contains(frase, palavra)
}

// verificaContem é um helper: t.Helper() faz o erro apontar para o teste chamador.
func verificaContem(t *testing.T, frase, palavra string, esperado bool) {
	t.Helper()
	obtido := Contem(frase, palavra)
	if obtido != esperado {
		t.Errorf("Contem(%q, %q) = %v; esperado %v", frase, palavra, obtido, esperado)
	}
}

func TestContem(t *testing.T) {
	casos := []struct {
		nome     string
		frase    string
		palavra  string
		esperado bool
	}{
		{"palavra presente", "golang é legal", "golang", true},
		{"palavra ausente", "golang é legal", "rust", false},
		{"case sensitive", "Golang", "golang", false},
		{"string vazia", "qualquer", "", true},
	}

	for _, c := range casos {
		t.Run(c.nome, func(t *testing.T) {
			verificaContem(t, c.frase, c.palavra, c.esperado)
		})
	}
}

Passo a passo

  1. Contem delega para strings.Contains, que já faz a checagem de substring.
  2. O helper verificaContem recebe t, os parâmetros e o valor esperado.
  3. A primeira linha do helper é t.Helper(), que marca essa função como auxiliar.
  4. Calculamos obtido := Contem(frase, palavra) e comparamos com esperado.
  5. Em caso de falha, t.Errorf imprime os valores com %q para deixar claro o que foi testado.
  6. No teste, cada caso da tabela é executado dentro de t.Run, isolando as falhas.

Por que funciona

t.Helper() altera o relatório de falhas: sem ele, o go test apontaria para a linha do t.Errorf dentro do helper, o que confunde. Com t.Helper(), o arquivo e a linha reportados são os do teste que chamou o helper, tornando o diagnóstico direto.

Combinado com table-driven e t.Run, temos testes curtos, com nomes significativos e mensagens de erro específicas — exatamente o estilo idiomático de Go.

Erros comuns

  • Esquecer t.Helper(): o erro aponta para o helper e não para o teste, dificultando a leitura.
  • Chamar t.Helper() depois de t.Errorf: a marcação precisa vir antes de qualquer reporte.
  • Usar t.Fatal no helper quando se quer continuar os outros casos — Fatal encerra o subteste atual; para o conjunto, prefira Errorf.

Outra forma de resolver

Sem helper, repetindo a verificação dentro do loop:

if Contem(c.frase, c.palavra) != c.esperado {
	t.Errorf("falhou: %s", c.nome)
}

É preferível quando a verificação aparece em um único lugar; o helper compensa quando a mesma checagem é usada em vários testes.

Saída esperada

=== RUN   TestContem
=== RUN   TestContem/palavra_presente
=== RUN   TestContem/palavra_ausente
=== RUN   TestContem/case_sensitive
=== RUN   TestContem/string_vazia
--- PASS: TestContem (0.00s)
    --- PASS: TestContem/palavra_presente (0.00s)
    --- PASS: TestContem/palavra_ausente (0.00s)
    --- PASS: TestContem/case_sensitive (0.00s)
    --- PASS: TestContem/string_vazia (0.00s)
PASS
ok  	textos	0.002s