Introduction : Pourquoi les tests en Go sont essentiels
Go (Golang) a été conçu avec la simplicité et la fiabilité en tête. Le package intégré testing est l'un des meilleurs outils pour écrire des tests parmi les langages modernes. Il ne nécessite pas de bibliothèques tierces pour les scénarios de base, tout en étant facilement extensible. Dans cet article, nous allons aborder trois niveaux de tests : unit, intégration et e2e. Vous apprendrez comment les écrire, quand les utiliser et quels outils employer. Ce contenu sera utile aussi bien aux débutants qu'aux développeurs Go expérimentés.
1. Tests unitaires en Go : les bases fondamentales
Les tests unitaires vérifient des fonctions ou méthodes individuelles de manière isolée. En Go, il suffit de créer un fichier avec le suffixe _test.go et d'écrire des fonctions de la forme TestXxx(t *testing.T).
Exemple simple de test unitaire
Supposons que nous ayons une fonction d'addition :
// math.gopackage main
func Add(a, b int) int { return a + b}Son test :
// math_test.gopackage main
import "testing"
func TestAdd(t *testing.T) { result := Add(2, 3) expected := 5 if result != expected { t.Errorf("Add(2, 3) = %d; want %d", result, expected) }}Tests table-driven (Table-Driven Tests)
La communauté Go recommande d'utiliser des tests table-driven pour vérifier plusieurs cas :
func TestAddTable(t *testing.T) { tests := []struct { name string a, b int want int }{ {"positive", 2, 3, 5}, {"negative", -1, -2, -3}, {"zero", 0, 0, 0}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := Add(tt.a, tt.b); got != tt.want { t.Errorf("Add() = %d, want %d", got, tt.want) } }) }}Les tests unitaires se lancent avec la commande :
go test ./...2. Tests d'intégration : vérifier les interactions
Les tests d'intégration vérifient comment différentes parties du système fonctionnent ensemble : base de données, API, système de fichiers. En Go, on les place généralement dans des fichiers séparés avec une balise de compilation ou dans un package integration.
Utilisation des build tags
Créez un fichier integration_test.go avec la balise :
//go:build integration
package integration
import ( "database/sql" "testing" _ "github.com/lib/pq")
func TestDatabaseConnection(t *testing.T) { dsn := "host=localhost port=5432 user=test dbname=test sslmode=disable" db, err := sql.Open("postgres", dsn) if err != nil { t.Fatalf("Failed to open DB: %v", err) } defer db.Close()
err = db.Ping() if err != nil { t.Fatalf("Failed to ping DB: %v", err) }}Exécution uniquement des tests d'intégration :
go test -tags=integration ./...Travailler avec une base de données de test
Pour les tests d'intégration, on utilise souvent testcontainers-go ou une base de données en mémoire (ex. SQLite). Exemple avec testcontainers :
func TestWithPostgresContainer(t *testing.T) { ctx := context.Background() pgContainer, err := postgres.RunContainer(ctx, testcontainers.WithImage("postgres:15"), postgres.WithDatabase("testdb"), ) require.NoError(t, err) defer pgContainer.Terminate(ctx)
dsn, _ := pgContainer.ConnectionString(ctx) // utiliser dsn pour la connexion}3. Tests E2E : vérifier le système dans son ensemble
Les tests End-to-End simulent le comportement de l'utilisateur et vérifient l'ensemble du système du début à la fin. En Go, ils sont souvent écrits pour les services HTTP en utilisant le package net/http/httptest.
Exemple de test E2E pour une API REST
func TestCreateUserE2E(t *testing.T) { // Z