Tests d'intégration Rust avec Docker : niveau avancé

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Tests d'intégration Rust avec Docker : niveau avancé



Les tests d'intégration sont une étape cruciale du développement en Rust, surtout lorsque votre application interagit avec des services externes : bases de données, files d'attente de messages, API HTTP. L'utilisation de Docker permet de créer des environnements de test isolés et reproductibles. Dans cet article, nous aborderons des techniques avancées : de la configuration de base à l'exécution parallèle des tests avec testcontainers et docker-compose.



Pourquoi Docker pour les tests d'intégration ?

Les mocks et stubs traditionnels ne reflètent souvent pas le comportement réel des dépendances. Docker résout ce problème :

  • Isolation : chaque test s'exécute dans un conteneur propre.
  • Reproductibilité : environnement identique sur toutes les machines des développeurs et dans le CI.
  • Parallélisme : possibilité d'exécuter plusieurs bases de données de test simultanément.


1. Configuration de base : test avec PostgreSQL

Commençons simplement : testons une fonction qui interagit avec PostgreSQL. Utilisons la crate testcontainers — un wrapper Rust pour gérer les conteneurs Docker.

Ajoutez les dépendances dans Cargo.toml :

[dev-dependencies]testcontainers = "0.18"tokio = { version = "1", features = ["full"] }sqlx = { version = "0.8", features = ["runtime-tokio", "postgres"] }


Exemple de test :

use sqlx::PgPool;use testcontainers::clients::Cli;use testcontainers::images::postgres::Postgres;

#[tokio::test]async fn test_database_connection() { let docker = Cli::default(); let postgres_instance = docker.run(Postgres::default()); let connection_string = &format!( "postgres://postgres:postgres@127.0.0.1:{}/postgres", postgres_instance.get_host_port_ipv4(5432) );

let pool = PgPool::connect(connection_string).await.unwrap();

// Exécution d'une requête SQL let row: (i32,) = sqlx::query_as("SELECT 1 + 1") .fetch_one(&pool) .await .unwrap(); assert_eq!(row.0, 2);}

Important : le conteneur est automatiquement supprimé après la fin du test (grâce à l'implémentation de Drop).



2. Configuration avancée : image personnalisée avec migrations

Il est souvent nécessaire d'exécuter des migrations au préalable. Créons une image personnalisée basée sur un Dockerfile :

# Dockerfile.testFROM postgres:16-alpineCOPY migrations/ /docker-entrypoint-initdb.d/


Dans le test Rust, utilisons Image :

use testcontainers::images::generic::GenericImage;

#[tokio::test]async fn test_with_migrations() { let docker = Cli::default(); let image = GenericImage::new("my-app-test:latest") .with_wait_for(testcontainers::core::WaitFor::message_on_stdout( "database system is ready to accept connections" )); let instance = docker.run(image); // ... utilisation de instance}

Pour construire l'image dans le CI, vous pouvez utiliser docker build -f Dockerfile.test -t my-app-test:latest .



3. Exécution parallèle des tests avec Docker Compose

Si votre service nécessite plusieurs dépendances (PostgreSQL + Redis), utilisez docker-compose. Créez un fichier docker-compose.test.yml :

version: '3.8'services:  postgres:    image: postgres:16-alpine    environment:      POSTGRES_PASSWORD: testpass    ports:      - "5432"  redis:    image: redis:7-alpine    ports:      - "6379"


Dans le test Rust, lancez l'environnement Compose :

use testcontainers::clients::Cli;use testcontainers::images::compose::Compose;

#[tokio::test]async fn test_with_compose() { let docker = Cli::default(); let compose = Compose::new("docker-compose.test.y

Blogs

Book Recommendations