Glossaire · CI/CD et DevOps
Testcontainers
Également appelé : Testcontainers for Java, testcontainers-node, Testcontainers Java
Définition
Bibliothèque qui démarre de vraies dépendances, comme des bases de données, des brokers ou des navigateurs, dans des conteneurs Docker jetables depuis votre code de test.
Testcontainers est une bibliothèque open source, disponible pour Java, Node.js, .NET, Go, Python et d’autres langages, qui pilote Docker depuis vos tests. Un test demande « une base Postgres 16 », la bibliothèque démarre un conteneur, attend qu’il soit prêt, vous fournit les informations de connexion et supprime le conteneur à la fin du test. Vous testez contre le vrai moteur de base de données au lieu d’un substitut en mémoire ou d’un environnement partagé.
Exemple (Testcontainers for Java 1.x, JUnit 5)
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import static org.junit.jupiter.api.Assertions.assertTrue;
@Testcontainers
class DatabaseIT {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine");
@Test
void canQueryTheDatabase() throws Exception {
try (Connection conn = DriverManager.getConnection(
postgres.getJdbcUrl(), postgres.getUsername(), postgres.getPassword());
ResultSet rs = conn.createStatement().executeQuery("SELECT 1")) {
assertTrue(rs.next());
}
}
}
Un champ static partage un seul conteneur entre tous les tests de la classe ; un champ d’instance en démarrerait un nouveau pour chaque test. Dans une vraie suite, vous feriez pointer votre repository ou votre contexte Spring vers getJdbcUrl() et exécuteriez d’abord les migrations.
Pourquoi c’est important
Les tests d’intégration sur H2 ou SQLite passent souvent alors que la base de production rejette le même SQL, car les dialectes, les contraintes et le comportement transactionnel diffèrent. Testcontainers vous donne le vrai moteur avec presque la commodité d’un mock, et chaque exécution démarre d’un état propre, ce qui élimine l’instabilité liée aux données partagées.
À savoir
- Il faut un runtime compatible Docker sur la machine et sur les runners de CI. Les runners Ubuntu hébergés par GitHub disposent de Docker.
- Le démarrage d’un conteneur coûte quelques secondes. Partagez les conteneurs par classe ou par suite, et réinitialisez les données entre les tests plutôt que de redémarrer le conteneur.
- Figez les versions des images pour qu’elles correspondent à la production.
- Des modules prêts à l’emploi existent pour les services courants (Postgres, MySQL, Kafka, LocalStack, Selenium, etc.), et
GenericContainercouvre n’importe quelle autre image. - Il complète les doublures de test plutôt qu’il ne les remplace : les tests unitaires doivent rester en mémoire et rapides.