<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://wiki.squi.fr/index.php?action=history&amp;feed=atom&amp;title=Rust_%3A_tests_automatis%C3%A9s</id>
	<title>Rust : tests automatisés - Historique des versions</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.squi.fr/index.php?action=history&amp;feed=atom&amp;title=Rust_%3A_tests_automatis%C3%A9s"/>
	<link rel="alternate" type="text/html" href="https://wiki.squi.fr/index.php?title=Rust_:_tests_automatis%C3%A9s&amp;action=history"/>
	<updated>2026-06-12T03:27:28Z</updated>
	<subtitle>Historique des versions pour cette page sur le wiki</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://wiki.squi.fr/index.php?title=Rust_:_tests_automatis%C3%A9s&amp;diff=2369&amp;oldid=prev</id>
		<title>Justine : Page créée avec « &lt;syntaxhighlight lang=&#039;rust&#039;&gt; // Automated tests // Le principe d&#039;un test est de faire 3 choses à la suite: // * Préparer un état / des données nécessaires  // * Faire tourner le code à tester // * Vérifier les résultats // // Le principe le plus simple est d&#039;ajouter la métadonnée: // #[test] // à une fonction, est de la tester avec cargo test. // // Lors de la création d&#039;une lib, un module de test est généré  // automatiquement.  //Reprenons notre... »</title>
		<link rel="alternate" type="text/html" href="https://wiki.squi.fr/index.php?title=Rust_:_tests_automatis%C3%A9s&amp;diff=2369&amp;oldid=prev"/>
		<updated>2022-11-03T14:49:21Z</updated>

		<summary type="html">&lt;p&gt;Page créée avec « &amp;lt;syntaxhighlight lang=&amp;#039;rust&amp;#039;&amp;gt; // Automated tests // Le principe d&amp;#039;un test est de faire 3 choses à la suite: // * Préparer un état / des données nécessaires  // * Faire tourner le code à tester // * Vérifier les résultats // // Le principe le plus simple est d&amp;#039;ajouter la métadonnée: // #[test] // à une fonction, est de la tester avec cargo test. // // Lors de la création d&amp;#039;une lib, un module de test est généré  // automatiquement.  //Reprenons notre... »&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Nouvelle page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;#039;rust&amp;#039;&amp;gt;&lt;br /&gt;
// Automated tests&lt;br /&gt;
// Le principe d&amp;#039;un test est de faire 3 choses à la suite:&lt;br /&gt;
// * Préparer un état / des données nécessaires &lt;br /&gt;
// * Faire tourner le code à tester&lt;br /&gt;
// * Vérifier les résultats&lt;br /&gt;
//&lt;br /&gt;
// Le principe le plus simple est d&amp;#039;ajouter la métadonnée:&lt;br /&gt;
// #[test]&lt;br /&gt;
// à une fonction, est de la tester avec cargo test.&lt;br /&gt;
//&lt;br /&gt;
// Lors de la création d&amp;#039;une lib, un module de test est généré &lt;br /&gt;
// automatiquement.&lt;br /&gt;
&lt;br /&gt;
//Reprenons notre struct Rectangle.&lt;br /&gt;
#[derive(Debug)]&lt;br /&gt;
struct Rectangle {&lt;br /&gt;
    width: u32,&lt;br /&gt;
    height: u32,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
impl Rectangle {&lt;br /&gt;
    fn can_hold(&amp;amp;self, other: &amp;amp;Rectangle) -&amp;gt; bool {&lt;br /&gt;
        self.width &amp;gt; other.width &amp;amp;&amp;amp; self.height &amp;gt; other.height&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Fonction diverses utilisées plus tard&lt;br /&gt;
//(Ce sont les fonctions que l&amp;#039;on teste)&lt;br /&gt;
fn add_two(a: i32) -&amp;gt; i32 {&lt;br /&gt;
    a + 2&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
pub fn greeting(name: &amp;amp;str) -&amp;gt; String {&lt;br /&gt;
    format!(&amp;quot;Hello {}!&amp;quot;, name)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
pub struct Guess {&lt;br /&gt;
    value: i32,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
impl Guess {&lt;br /&gt;
    pub fn new(value: i32) -&amp;gt; Guess {&lt;br /&gt;
        if value &amp;lt; 1 {&lt;br /&gt;
            panic!(&lt;br /&gt;
                &amp;quot;Guess value must be greater than or equal to 1, got {}.&amp;quot;,&lt;br /&gt;
                value&lt;br /&gt;
            );&lt;br /&gt;
        } else if value &amp;gt; 100 {&lt;br /&gt;
            panic!(&lt;br /&gt;
                &amp;quot;Guess value must be less than or equal to 100, got {}.&amp;quot;,&lt;br /&gt;
                value&lt;br /&gt;
            );&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        Guess { value }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
fn prints_and_returns_10(a: i32) -&amp;gt; i32 {&lt;br /&gt;
    println!(&amp;quot;I got the value {}&amp;quot;, a);&lt;br /&gt;
    10&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Partie tests&lt;br /&gt;
#[cfg(test)]&lt;br /&gt;
mod tests {&lt;br /&gt;
    //Le module de tests est un module normal qui suit les règles&lt;br /&gt;
    //de visibilité.&lt;br /&gt;
    //Pour rappel, super rappelle des modules du parent.&lt;br /&gt;
    //On ramène tout le contenu du parent.&lt;br /&gt;
    use super::*;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    //Cette metadata signifie au compilateur que c&amp;#039;est une fonction de test&lt;br /&gt;
    //Elle peut être accompagnée de fonctiosn non-test dont elle aurait&lt;br /&gt;
    //besoin&lt;br /&gt;
    #[test]&lt;br /&gt;
    fn exploration() {&lt;br /&gt;
        let result = 2 + 2;&lt;br /&gt;
        //assert_eq! sert à vérifier une égalité&lt;br /&gt;
        //assert_ne! sert à vérifier une non-égalité&lt;br /&gt;
        assert_eq!(result, 4);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    //Ce test échoue volontairement pour voir ce que ça fait&lt;br /&gt;
    //lors d&amp;#039;un cargo test.&lt;br /&gt;
    //#[test]&lt;br /&gt;
    //fn another() {&lt;br /&gt;
    //    panic!(&amp;quot;I was born by the failure, moulded by it&amp;quot;);&lt;br /&gt;
    //}&lt;br /&gt;
&lt;br /&gt;
    //On teste l&amp;#039;implémentation de notre struct Rectangle.&lt;br /&gt;
    //Notre impl can_hold renvoie un booléen, c&amp;#039;est parfait&lt;br /&gt;
    #[test]&lt;br /&gt;
    fn larger_can_hold_smaller() {&lt;br /&gt;
        let larger = Rectangle {&lt;br /&gt;
            width: 8,&lt;br /&gt;
            height: 7,&lt;br /&gt;
        };&lt;br /&gt;
        let smaller = Rectangle {&lt;br /&gt;
            width: 5,&lt;br /&gt;
            height: 1,&lt;br /&gt;
        };&lt;br /&gt;
        //assert! vérifie un booléen.&lt;br /&gt;
        assert!(larger.can_hold(&amp;amp;smaller));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    //Autre test : on vérifie qu&amp;#039;un rectangle ne peut pas&lt;br /&gt;
    //contenir un autre rectangle plus grand.&lt;br /&gt;
    #[test]&lt;br /&gt;
    fn smaller_cant_hold_larger() {&lt;br /&gt;
        let larger = Rectangle {&lt;br /&gt;
            width : 20,&lt;br /&gt;
            height : 21&lt;br /&gt;
        };&lt;br /&gt;
        let smaller = Rectangle {&lt;br /&gt;
            width : 10,&lt;br /&gt;
            height : 15&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        assert!(!smaller.can_hold(&amp;amp;larger));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    //Démonstration de assert_eq!&lt;br /&gt;
    //Les paramètre d&amp;#039;une assertion s&amp;#039;appellent left et right,&lt;br /&gt;
    //c&amp;#039;est bon à savoir pour comprendre les messages d&amp;#039;erreur&lt;br /&gt;
    //sur un test raté&lt;br /&gt;
    #[test]&lt;br /&gt;
    fn test_add_two() {&lt;br /&gt;
        assert_eq!(4, add_two(2));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    //Démonstration de assert_ne!&lt;br /&gt;
    #[test]&lt;br /&gt;
    fn test_not_add_two() {&lt;br /&gt;
        assert_ne!(5, add_two(2));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //Ce test échoue volontairement.&lt;br /&gt;
    //#[test]&lt;br /&gt;
    //fn greeting_contains_name() {&lt;br /&gt;
    //    let result = greeting(&amp;quot;Justine&amp;quot;);&lt;br /&gt;
    //    //On peut ajouter un message en cas d&amp;#039;erreur.&lt;br /&gt;
    //    //Le message est un format!.&lt;br /&gt;
    //    assert!(&lt;br /&gt;
    //        result.contains(&amp;quot;Hi&amp;quot;),&lt;br /&gt;
    //        &amp;quot;Greeting did not contain Hi, value was {}&amp;quot;,&lt;br /&gt;
    //        result&lt;br /&gt;
    //    );&lt;br /&gt;
    //}&lt;br /&gt;
&lt;br /&gt;
    //On peut vérifier une panique.&lt;br /&gt;
    //Ici, je m&amp;#039;attends à ce que le code panique.&lt;br /&gt;
    //J&amp;#039;aurais cette ligne dans le retour de cargo test:&lt;br /&gt;
    //test tests::greater_than_100 - should panic ... ok&lt;br /&gt;
    #[test]&lt;br /&gt;
    #[should_panic]&lt;br /&gt;
    fn greater_than_100() {&lt;br /&gt;
        Guess::new(200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    //Un test de panique n&amp;#039;est pas forcément précis.&lt;br /&gt;
    //Je peux préciser quelle panique je dois récupérer.&lt;br /&gt;
    //Si ce n&amp;#039;est pas &amp;quot;less than or equal to 100&amp;quot;, le test fail.&lt;br /&gt;
    #[test]&lt;br /&gt;
    #[should_panic(expected = &amp;quot;less than or equal to 100&amp;quot;)]&lt;br /&gt;
    fn greater_than_100_precise() {&lt;br /&gt;
        Guess::new(200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    //On peut aussi écrire un test qui utilise un Result.&lt;br /&gt;
    //On a alors pas accès au should_panic, mais on a accès au ?&lt;br /&gt;
    //dans nos tests.&lt;br /&gt;
    //Par défaut, si le test reçoit Ok, il est content.&lt;br /&gt;
    //Je pourrais ajouter assert!(mavaleur.is_err())&lt;br /&gt;
    //si je m&amp;#039;attends à une erreur.&lt;br /&gt;
    #[test]&lt;br /&gt;
    fn it_works() -&amp;gt; Result&amp;lt;(), String&amp;gt; {&lt;br /&gt;
        if 2 + 2 == 4 {&lt;br /&gt;
            Ok(())&lt;br /&gt;
        } else {&lt;br /&gt;
            Err(String::from(&amp;quot;2 + 2 != 4, somehow&amp;quot;))&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    //Contrôler l&amp;#039;exécution des tests&lt;br /&gt;
    //Il existe plusieurs options, à la fois pour cargo test en lui-même&lt;br /&gt;
    //et pour le binaire généré par celui-ci.&lt;br /&gt;
    //Les options sont disposées comme suit:&lt;br /&gt;
    //cargo test &amp;lt;options de cargo&amp;gt; -- &amp;lt;options du binaire&amp;gt;&lt;br /&gt;
    //&lt;br /&gt;
    //Tests en parrallèle / consécutifs&lt;br /&gt;
    //Par défaut, cargo lance les tests en parrallèle sur divers threads.&lt;br /&gt;
    //Du coup, les tests ne doivent pas dépendre les uns des autres.&lt;br /&gt;
    //On peut changer ça comme ça:&lt;br /&gt;
    //cargo test -- --test-threads=1&lt;br /&gt;
    //&lt;br /&gt;
    //Montrer les sorties de fonctions&lt;br /&gt;
    //Par défaut, les tests n&amp;#039;affichent rien sur la sortie standard;&lt;br /&gt;
    //un println! ne montrera rien.&lt;br /&gt;
    #[test]&lt;br /&gt;
    fn this_test_will_pass() {&lt;br /&gt;
        let value = prints_and_returns_10(4);&lt;br /&gt;
        assert_eq!(10, value);&lt;br /&gt;
    }&lt;br /&gt;
    //On peut afficher la sortie avec&lt;br /&gt;
    //cargo test -- --show-output&lt;br /&gt;
    &lt;br /&gt;
    //Lancer un ensemble de tests par un nom&lt;br /&gt;
    //On ne veut pas forcément lancer tous les tests;&lt;br /&gt;
    //on peut appeller unue fonction de test en particulier:&lt;br /&gt;
    //cargo test nom_fonction&lt;br /&gt;
    &lt;br /&gt;
    //On peut aussi utiliser un filtre pour lancer plusieurs fonctions.&lt;br /&gt;
    //De la même façon, on peut passer le début d&amp;#039;un nom de fonction;&lt;br /&gt;
    //toutes les fonctions qui matchent ce début de nom seront testées.&lt;br /&gt;
    //cargo test greater_than&lt;br /&gt;
    &lt;br /&gt;
    //On peut aussi ignorer des tests à moins de les appeller spécifiquement,&lt;br /&gt;
    //un peu comme un tag never dans Ansible.&lt;br /&gt;
    #[test]&lt;br /&gt;
    #[ignore]&lt;br /&gt;
    fn expensive_test() {&lt;br /&gt;
        // code that takes an hour to run&lt;br /&gt;
    }&lt;br /&gt;
    //...on peut alors appeller les tests ignorés:&lt;br /&gt;
    //cargo test -- --ignored&lt;br /&gt;
    //Ou tous les tests&lt;br /&gt;
    //cargo test -- --include-ignored&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    //Les tests en Rust sont généralement divisés en 2 types:&lt;br /&gt;
    //* Les tests unitaires sont sont petits et concentrés sur un&lt;br /&gt;
    //module à la fois&lt;br /&gt;
    //* Les tests d&amp;#039;intégration sont externes au code et utilisent le code &lt;br /&gt;
    //comme le ferait une librairie externe, en utilisant seulement les &lt;br /&gt;
    //interfaces publiques.&lt;br /&gt;
    //Les deux sont importants.&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    // Tests unitaires&lt;br /&gt;
    //Ils vont dans le répertoire src, dans le même fichier que le code&lt;br /&gt;
    //qu&amp;#039;ils servent à tester. La convention est d&amp;#039;avoir un module nommé tests&lt;br /&gt;
    //dans chacun de ces fichiers, et de l&amp;#039;annoter avec cfg(test).&lt;br /&gt;
&lt;br /&gt;
    //L&amp;#039;annotation #[cfg(test)] permet de faire tourner ce code seulement lors &lt;br /&gt;
    //de l&amp;#039;appel via cargo test, et pas build. On peut tester les &lt;br /&gt;
    //fonctions privées.&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    // Tests d&amp;#039;intégration&lt;br /&gt;
    //Comme dit, ils sont externes. Ils servent à savoir si notre lib va&lt;br /&gt;
    //bien fonctionner avec du code externe.&lt;br /&gt;
    //Ils vont dans un répertoire nommé tests, situé à côté de src.&lt;br /&gt;
    //J&amp;#039;en recopie un ici juste pour expliquer, mais il devrait aller dans&lt;br /&gt;
    //le répertoire tests/integration_test.rs; on suppose aussi que la présente &lt;br /&gt;
    //librairie s&amp;#039;appelle adder comme précisé dans Cargo.toml&lt;br /&gt;
    //Le présent fichier doit s&amp;#039;appeller lib.rs !&lt;br /&gt;
    //use adder;&lt;br /&gt;
&lt;br /&gt;
    //#[test]&lt;br /&gt;
    //fn it_adds_two() {&lt;br /&gt;
    //    assert_eq!(4, adder::add_two(2));&lt;br /&gt;
    //}&lt;br /&gt;
    //&lt;br /&gt;
    //Je peux le lancer avec cargo test --test integration_test&lt;br /&gt;
    //A noter : pas besoin du #[cfg(test)] ici&lt;br /&gt;
    //Par ailleurs les tests d&amp;#039;intégration ne fonctionnent qu&amp;#039;avec&lt;br /&gt;
    //une lib crate, et pas une crate binaire avec un main.rs;&lt;br /&gt;
    //seule une lib expose des fonctions.&lt;br /&gt;
    //&lt;br /&gt;
    //Le plus courant est d&amp;#039;avoir une lib crate contenant&lt;br /&gt;
    //un lib.rs et un main.rs&lt;br /&gt;
&lt;br /&gt;
    //Submodules dans les test d&amp;#039;intégration&lt;br /&gt;
    //On peut d&amp;#039;ailleurs avoir des sous modules dans les tests d&amp;#039;intégration.&lt;br /&gt;
    //On peut faire plusieurs fichiers dans le répertoire tests;&lt;br /&gt;
    //contrairement à src, ils sont traités comme des crates différentes.&lt;br /&gt;
    //Par défaut tout est pris en compte par cargo test.&lt;br /&gt;
    //&lt;br /&gt;
    //Si on veut qu&amp;#039;un sous-module (qui par exemple ne sert que de helper&lt;br /&gt;
    //aux véritables modules de test) soit ignoré, on va créer &lt;br /&gt;
    // /tests/common/mod.rs&lt;br /&gt;
    //On aura donc:&lt;br /&gt;
    //├── Cargo.lock&lt;br /&gt;
    //├── Cargo.toml&lt;br /&gt;
    //├── src&lt;br /&gt;
    //│   └── lib.rs&lt;br /&gt;
    //└── tests&lt;br /&gt;
    //    ├── common&lt;br /&gt;
    //    │   └── mod.rs&lt;br /&gt;
    //    └── integration_test.rs&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Justine</name></author>
	</entry>
</feed>