Como escrever uma suite de testes em Go

Como escrever suites de teste em Go usando o pacote testify

Como escrever uma suite de testes em Go

Na parte 2 da série "Pensando em testes" fiz uma menção ao conceito de suite de testes. Agora vou te ensinar a implementar uma usando Go. Uma suite de testes nada mais é que um agregador de outros testes, e este é um recurso importante para que esta parte vital do código do seu projeto seja mais fácil de ser mantida.

Pensando em testes
Nossa série de posts sobre como melhorar a manutenibilidade da sua base de código de testes! Pensando em testes - Parte 1Uma nova série de posts - Pensando em testes: como evitar que seus testes automatizados se tornem um problema.itexto InsightsHenrique Lobo WeissmannPensando em testes - Parte 2 -

Acompanhe a nossa série "Pensando em testes"!

Ingredientes

Passo a passo

Identifique os testes

O primeiro passo consiste em identificar o conjunto de testes que irão validar uma funcionalidade ou comportamento específico do seu sistema.

💡
Ficou difícil identificar este grupo de testes? Talvez haja um problema na qualidade do código do seu projeto OU mesmo na sua visão arquitetural. Ligue o alerta agora!

No nosso caso de exemplo iremos tratar de testes que validem o processo de autenticação de usuários na nossa plataforma. Iremos tratar aqui testes de integração, que realizam chamadas contra o nosso endpoint de autenticação. Já pensamos em alguns casos:

  • Autenticação mal sucedida ao informar credenciais inválidas
  • Uma autenticação bem sucedida fornecendo credenciais válidas
  • Autenticação bem sucedida de um usuário associado a um tenant.
  • Autenticação mal sucedida de um usuário que tenta acessar um tenant que não é o seu.

Escrevendo a suite de testes

Se você já escreveu testes em Go, a situação não muda muito: a principal diferença é que começamos pela definição de uma struct. E é esta struct que conterá todos os métodos que corresponderão aos testes que iremos escrever.

Criando a struct principal para nossa suite

Comece criando um arquivo de testes seguindo o padrão do Go para que estes possam ser identificados: um simples arquivo que termine com o sufixo "test". Em nosso exemplo se chamará auth_suite_test.go e que será similar ao exemplo a seguir:

package tests

import (
	"encoding/json" //apenas para nosso exempl
	"fmt" // apenas para nosso exemplo
	"net/http" // apenas para nosso exemplo
	"net/http/httptest" // apenas para nosso exemplo
	"strings" //apenas para nosso exemplo


	"testing" // você precisa do testing do Go

	"github.com/gin-gonic/gin" // apenas par anosso exemplo
	

    "github.com/stretchr/testify/suite" // este você precisa! :)
)

/*
	Contempla todos os casos de testes de acesso na plataforma em
	um teste suite.
*/

type AcessoTestSuite struct {
	router *gin.Engine
	suite.Suite
}

Observe que importamos o pacote github.com/stretchr/sute e na sequência criamos a nossa struct que contém dois atributos: o Engine do Gin, presente no nosso projeto de exemplo, e também um atributo do tipo suite.Suite que iremos usar na execução dos nossos testes.

Escrevendo os nossos testes

func (suite *AcessoTestSuite) TestAcessoNegadoUsuarioInexistente() {

	request := utils.CredentialsRequest{
		Username: "inexistente@inexistente.com",
		Password: "SuperInexistenteMesmo!",
	}
	w := httptest.NewRecorder()
	requestJson, _ := json.Marshal(request)

	requestJsonString := string(requestJson)
	req, _ := http.NewRequest("POST", "/api/v1/auth", strings.NewReader(requestJsonString))
	req.Header.Set("Content-Type", "application/json")
	suite.router.ServeHTTP(w, req)

	suite.Equal(http.StatusUnauthorized, w.Code)
}

Observe que é mantido o padrão da nomenclatura de nomes de testes do Go: nossa função começa com o prefixo Test e está associada à struct. A partir dela podemos acessar também assertions, como Equal, tal como você pode ver no nosso exemplo. Nada demais.

💡
Dica: use o testify como substituto da biblioteca padrão de testes do Go. É bem melhor: te dá suporte a suites, assertions e mais algumas funcionalidades bem úteis que não existem na biblioteca padrão.

Visite o site do projeto para aprender mais: http://github.com/stretchr/testify

Na sequência, escreva os demais testes seguindo os padrões acima.

Preparo da suite de testes - SetupAllSuite

Notou que na suite de testes eu uso o roteador do Gin para realizar minha validação? É possível definir uma função que será executada antes de todos os testes da suite. Isto é particularmente útil no caso de testes integrados, aonde você pode executar código como migrations, início de serviços externos, etc.

O nome da função a ser implementada se chama SetupAllSuite, e você pode ver um exemplo de implementação no código abaixo:

func (suite *AcessoTestSuite) SetupAllSuite() {
	fmt.Println("Setup da suite de testes")
	err := setup.SetupTests()
	suite.Nil(err)
	suite.router = endpoints.SetupRouter()
	fmt.Println("Setup da suite de testes realizada com sucesso")
}

É ali que já definimos o valor do atributo router da struct AcessoTestSuite e também executamos uma única vez - para todos os testes - o código de inicialização da suite: em nosso caso preparo do banco de dados (do módulo setup que menciono ali, específico da nossa situação).

Limpando o caos que sua suite de testes pode ter craido - TearDownAllSuite

É o oposto de SetupSuite: você escreve nesta função o código que irá limpar as estruturas de dados, registros em banco de dados ou qualquer coisa que sua suite de testes pode ter executado.

💡
É um excelente ponto para colocar código que execute rollback em transações, por exemplo.

Exemplo simples? Bora lá:

func (suite *AcessoTestSuite) TearDownAllSuite() {
      // código fictício
      suite.transaction.rollback()
}

Finalmente, executando a suite

Fácil: basta escrever um teste, fora da suite, que a inicie, tal como no exemplo a seguir:

func TestAcessoTestSuite(t *testing.T) {
	suite.Run(t, new(AcessoTestSuite))
}

Você usa a função Run, da struct suite, presente no módulo que você importou como github.com/stretchr/testify/suite para executar a instância da struct que criamos no início desta receita.

Concluindo com dica

Nesta receita apenas menciono o pacote testify, mas ele vai muito além: na nossa experiência é quase um substituto para a biblioteca de testes padrão do Go.

Dá uma lida na documentação presente no site oficial, você não vai se arrepender: https://github.com/stretchr/testify

Para ver mais sobre os métodos relativos à execução de suites de teste, acesse este link: https://pkg.go.dev/github.com/stretchr/testify/suite#Suite

Mantido por itexto Consultoria