Tests en Rust : unitaires, d'intégration, e2e de A à Z

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

Introduction : Pourquoi les tests en Rust sont la base d'un code fiable



Rust est un langage de programmation système réputé pour sa sécurité mémoire et ses performances. Cependant, même le compilateur le plus strict ne garantit pas que votre programme fait exactement ce qu'il faut. C'est là que les tests entrent en jeu. En Rust, le support intégré des tests est l'un des meilleurs parmi les langages modernes. Vous pouvez écrire des tests unitaires, des tests d'intégration et des tests e2e (de bout en bout) sans avoir besoin de bibliothèques externes.



Dans cet article, nous allons détailler les trois niveaux de tests avec des exemples pratiques. Vous apprendrez à écrire des tests, à les exécuter avec cargo test et à organiser l'infrastructure de test pour les grands projets.



1. Tests unitaires en Rust : tester les fonctions et les modules



Les tests unitaires vérifient le fonctionnement de fonctions ou de méthodes individuelles de manière isolée. En Rust, il est courant de placer les tests unitaires directement dans le fichier source, à l'intérieur d'un module tests avec l'annotation #[cfg(test)]. Cela permet aux tests d'accéder aux fonctions privées du module.



1.1. Premier test unitaire



Créons une bibliothèque simple pour les calculs et écrivons des tests pour celle-ci.



// src/lib.rspub fn add(a: i32, b: i32) -> i32 {    a + b}

pub fn divide(a: f64, b: f64) -> Result<f64, String> { if b == 0.0 { Err(String::from("Division par zéro")) } else { Ok(a / b) }}

#[cfg(test)]mod tests { use super::*;

#[test] fn test_add() { assert_eq!(add(2, 3), 5); }

#[test] fn test_divide_success() { let result = divide(10.0, 2.0).unwrap(); assert_eq!(result, 5.0); }

#[test] fn test_divide_by_zero() { let result = divide(10.0, 0.0); assert!(result.is_err()); assert_eq!(result.unwrap_err(), "Division par zéro"); }}


Exécutez les tests avec la commande cargo test. Vous verrez des coches vertes si tous les tests sont réussis.



1.2. Attributs des tests



  • #[test] — indique que la fonction est un test.
  • #[should_panic] — le test est considéré comme réussi si la fonction provoque une panique.
  • #[ignore] — désactive temporairement le test.


#[test]#[should_panic(expected = "message de panique")]fn test_panic() {    panic!("message de panique");}

#[test]#[ignore = "Test désactivé jusqu'à la correction du bug #42"]fn test_expensive() { // Test long}


2. Tests d'intégration : vérifier l'interaction des composants



Les tests d'intégration vérifient le fonctionnement de plusieurs modules ou dépendances externes ensemble. En Rust, ils sont placés dans un répertoire séparé tests/ à la racine du projet. Chaque fichier dans ce dossier est une crate de test distincte qui ne voit que l'API publique de votre bibliothèque.



2.1. Structure des tests d'intégration



Créez un dossier tests/ et un fichier tests/integration_test.rs :



// tests/integration_test.rsuse my_crate::add; // Nom de votre crate

#[test]fn test_add_integration() { // Vérifions que la fonction fonctionne comme partie de la bibliothèque let result = add(10, 20); assert_eq!(result, 30);}

#[test]fn test_divide_integration() { // Test avec plusieurs appels let a = 100.0; let b = 4.0; let result = my_crate::divide(a, b).unwrap(); assert!(result > 0.0); assert_eq!(result, 25.0);}


2.2. Modules communs pour les tests d'intégration



Si vous avez besoin de réutiliser du code entre les tests d'intégration, créez un fichier tests/common/mod.rs. Il ne sera pas considéré comme un fichier de test, mais vous pourrez l'importer depuis d'autres tests.



// tests/common/mod.rspub fn setu                

Blogs

Book Recommendations