Pular para o conteúdo principal

victorstein.dev

26/100 Dias de Golang - Testes em batch, AAA e Cobertura de Código

Table of Contents

# Testes em batch

Vamos adicionar mais alguns testes na função de soma, agora vamos testar com dois valores negativos, com somente um valor negativo e com zero.

func TestSomaTwoNegatives(t *testing.T) {
	total := Soma(-5, -10)

	expected := -15

	if total != expected {
		t.Errorf("Esperava %d recebi %d", expected, total)
	}
}

func TestSomaOneNegative(t *testing.T) {
	total := Soma(5, -10)

	expected := -5

	if total != expected {
		t.Errorf("Esperava %d recebi %d", expected, total)
	}
}

func TestSomaWithZero(t *testing.T) {
	total := Soma(5, 0)

	expected := 5

	if total != expected {
		t.Errorf("Esperava %d recebi %d", expected, total)
	}
}

O que você achou de todos esses testes? Não parece contraintuitivo gerar uma função para cada caso da função Soma? Só estamos trocando os parâmetros, parece desnecessário repetir toda a estrutura. Para resolver esse problema o Go possui o teste em batch. Veja como fazemos esse teste em batch.

func TestSomaInBatch(t *testing.T) {

	type sum struct {
		a, b, expected int
	}

	table := []sum{
		{5, 5, 10},
		{-5, -5, -10},
		{5, -5, 0},
		{0, 0, 0},
	}

	for _, item := range table {
		total := Soma(item.a, item.b)
		if total != item.expected {
			t.Errorf("Esperava %d recebi %d", item.expected, total)
		}
	}

}

Veja como esse código é simples, qualquer pessoa que entenda a sintaxe do Go conseguirá entendê-lo! Esse é um dos superpoderes do Golang.

Definimos uma struct com os parâmetros e com o valor esperado

type sum struct {
		a, b, expected int
	}

Depois criamos um slice com os casos que queremos testar

table := []sum{
	{5, 5, 10},
	{-5, -5, -10},
	{5, -5, 0},
	{0, 0, 0},
}

Após isso fazemos a verificação dentro de um for

for _, item := range table {
		total := Soma(item.a, item.b)
		if total != item.expected {
			t.Errorf("Esperava %d recebi %d", item.expected, total)
		}
	}

# Padrão AAA

O padrão AAA nos testes é uma sigla para Arrange, Act, Assert, que em português pode ser traduzido como Organizar, Agir, Afirmar. É um padrão usado para estruturar testes de forma clara e organizada. Veja o exemplo do teste TestSomaTwoNegatives

Arrange ou Organizar preparamos o cenário do teste. Isso inclui inicializar objetos, definir valores de entrada e configurar o ambiente necessário.

total := Soma(-5, -10)

Act ou Agir momento em que executamos a ação que está sendo testada.

func TestSomaTwoNegatives(t *testing.T) {
	total := Soma(-5, -10)
	
	expected := -15

	if total != expected {
		t.Errorf("Esperava %d recebi %d", expected, total)
	}
}

Assert ou Afirmar verificamos se o resultado obtido é o esperado.

func TestSomaTwoNegatives(t *testing.T) {
	total := Soma(-5, -10)
	
	expected := -15

	if total != expected {
		t.Errorf("Esperava %d recebi %d", expected, total)
	}
}

Lembre-se de que o teste também é um código! Devemos mantê-lo limpo, legível e fácil de manter.

# Cobertura de Testes

Cobertura de testes é uma métrica que indica o quanto do código de um sistema é testado. Ela ajuda a identificar partes do código que não estão sendo verificadas, permitindo melhorar a qualidade e a confiabilidade da aplicação. Embora uma alta cobertura não garanta a ausência de erros, ela é um bom indicativo de que o sistema foi amplamente testado. Li uma frase muito legal no livro “Arquitetura Limpa” do Uncle Bob,

Como Dijkstra disse um dia: “Os testes mostram a presença, não a ausência de bugs”.

Mesmo que o sistema esteja 100% coberto por testes, isso não prova que ele está livre de bugs ou que está completamente correto. Os testes tem a capacidade de nos mostrar a presença de bugs.

Com esse disclaimer feito, podemos passar para a cobertura de testes no Go. Muito simples para fazer a verificação, basta rodarmos o comando:

go test --coverprofile=coverage.out
PASS
coverage: 100.0% of statements
ok      firsttest       0.003s

Vamos adicionar mais uma função no utils.go

func Subtracao(a int, b int) int {
	return a - b
}

E rodar novamente o comando para verificar a cobertura de testes.

go test --coverprofile=coverage.out
PASS
coverage: 50.0% of statements
ok      firsttest       0.003s

Veja que é criado um arquivo na raiz do projeto, coverage.out. Podemos executar um comando para vermos o que não foi testado.

go tool cover -html=coverage.out

Veja a saída desse comando, em vermelho temos o que não foi testado e em verde o que foi testado.

Resultado do comando go tool cover -html=coverage.out