testcontainers-go : Docker dans les tests Go
Dans le développement logiciel moderne, tester les intégrations avec des services externes (bases de données, brokers de messages, caches) est l'une des tâches les plus complexes. Les approches traditionnelles, comme l'utilisation de bases de données de test partagées ou de mocks, entraînent souvent des problèmes : les tests deviennent fragiles, dépendent de l'environnement ou ne reflètent pas le comportement réel du système. La bibliothèque testcontainers-go propose une solution élégante : elle permet de lancer des conteneurs Docker isolés directement depuis le code de test Go, offrant ainsi un environnement propre, reproductible et proche de la production pour chaque exécution de test.
L'idée principale de testcontainers-go est de gérer le cycle de vie des conteneurs Docker par programmation. Vous décrivez le service nécessaire (par exemple, PostgreSQL, Redis, Kafka) dans le code du test, la bibliothèque télécharge automatiquement l'image (si elle n'est pas présente), lance le conteneur, attend qu'il soit prêt et vous fournit les paramètres de connexion (hôte, port, identifiants). Une fois le test terminé, le conteneur est automatiquement arrêté et supprimé, sans laisser de traces sur le système. Cela rend les tests indépendants, rapides et sécurisés.
testcontainers-go est l'implémentation Go du célèbre projet Testcontainers, initialement apparu en Java, puis porté vers d'autres langages. La bibliothèque est activement maintenue par la communauté et propose des modules prêts à l'emploi pour la plupart des services populaires : PostgreSQL, MySQL, Redis, MongoDB, Kafka, RabbitMQ, Elasticsearch et bien d'autres. Elle est idéale pour écrire des tests d'intégration, des tests end-to-end et même pour le développement local lorsqu'il faut rapidement monter un environnement.
Installation
Pour installer testcontainers-go, utilisez le gestionnaire de paquets standard de Go. Assurez-vous que Docker (ou Podman) et Go version 1.19 ou supérieure sont installés.
go get github.com/testcontainers/testcontainers-go
Pour travailler avec des services spécifiques (par exemple, PostgreSQL), vous devrez installer le module correspondant :
go get github.com/testcontainers/testcontainers-go/modules/postgres
go get github.com/testcontainers/testcontainers-go/modules/redis
go get github.com/testcontainers/testcontainers-go/modules/mongodb
go get github.com/testcontainers/testcontainers-go/modules/kafka
# etc.
Après l'installation, importez les paquets dans votre fichier de test :
import (
"context"
"testing"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
"github.com/testcontainers/testcontainers-go/modules/postgres"
)
Démarrage rapide : exemple minimal fonctionnel
Écrivons un test simple qui lance un conteneur PostgreSQL, crée une table, insère des données et les vérifie. Cela vous montrera les principes de base de la bibliothèque.
package main
import (
"context"
"database/sql"
"testing"
"time"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/modules/postgres"
"github.com/testcontainers/testcontainers-go/wait"
_ "github.com/lib/pq" // pilote PostgreSQL
)
func TestPostgresIntegration(t *testing.T) {
ctx := context.Background()
// 1. Lancement du conteneur PostgreSQL
postgresContainer, err := postgres.RunContainer(ctx,
testcontainers.WithImage("postgres:16-alpine"),
postgres.WithDatabase("testdb"),
postgres.WithUsername("testuser"),
postgres.WithPassword("testpass"),
testcontainers.WithWaitStrategy(
wait.ForLog("database system is ready to accept connections").
WithOccurrence(2).
WithStartupTimeout(60*time.Second)),
)
if err != nil {
t.Fatal(err)
}
defer postgres