diff --git a/tests.md b/tests.md index 73336e76dd373d68f4f02b0e09831fb677fd3b9b..021362e4f0a9e70814bcb988714ed26cba93e2da 100644 --- a/tests.md +++ b/tests.md @@ -1,11 +1,114 @@ --- title: Cours de programmation séquentielle -subtitle: Tests +subtitle: Tests automatiques author: Orestis Malaspinas sansfont: Sans Serif --- -# Tests +# Tests automatiques -Under construction +## A quoi ça sert? +- Nous permet d'avoir confiance en nos programmes. +- Tester que notre programme se comporte comme désiré. +- Le compilateur ne peut pas détecter tous les bugs possibles: les erreurs algorithmiques ne peuvent pas être détectées. +- Éviter les *régressions* lorsqu'on réécrit ou étend les fonctionalités d'un programme. +- Néanmois: **impossible** de tester si un programme est complètement correct (on ne peut pas tester *tous les cas*). +- Plus de détails et d'informations: [ici](https://doc.rust-lang.org/book/second-edition/ch11-00-testing.html) + +## Comment écrire un test + +En général un test effectue les trois actions suivantes: + +1. Mettre en place les données ou un état donné. +2. Exécuter le code à tester. +3. Vérifier si le résultat est celui attendu. + +## Exemple + +- Il est très aisé de voir l'anatomie d'un test très simple: +<pre><code data-trim="bash"> +cargo new projet_test --lib +</code></pre> + +- Création d'un projet avec le fichier `projet_test/src/lib.rs` +<pre><code data-trim="hljs rust"> + #[cfg(test)] +mod tests { + #[test] // la fonction suivant cette annotation sera exécutée comme test + fn it_works() { + assert_eq!(2 + 2, 4); // Vérification que l'addition fonctionne pour 2+2 + assert_ne!(2 + 2, 6); // utilisation de assert_ne! + assert!(2 + 2 == 4); // utilisation de assert! 2+2 + } +} +</code></pre> + +- Le test est exécuté avec `cargo test` +<pre><code data-trim="bash"> + Compiling projet_test v0.1.0 (projet_test) + Finished dev [unoptimized + debuginfo] target(s) in 0.45s + Running projet_test/target/debug/deps/projet_test-05539f5503f2a0fe\ +\ +running 1 test +test tests::it_works ... ok\ +\ +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out\ +\ + Doc-tests projet_test\ +\ +running 0 tests\ +\ +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out +</code></pre> + +## Tests de fonctions + +- Le test d'une fonction nécessite de la mettre dans la porté + +<pre><code data-trim="hljs rust"> + fn add_two(a: i32) -> i32 { + a + 2 +} + +#[cfg(test)] +mod tests { + use super::*; // mise en portée de tout ce qui est dans le module de dessus + + #[test] + fn test_add_two() { + assert_eq!(add_two(2), 4); // Vérification de la fonction add_two + } + + #[test] + fn test_add_two_custom_msg() { + // Ce test va paniquer à dessein, pour voir le message personnalisé. + assert_eq!(add_two(2) == 5, "Attention la somme 2+2 ne donne pas 5 mais {}.", 4); + } +} +</code></pre> + +## Tests devant paniquer + +- Si une erreur de logique est suffisamment grave pour faire paniquer le code on peut la panique: + +<pre><code data-trim="hljs rust"> + fn two_div_by(a: i32) -> i32 { + if a == 0 { + panic!("On nee peut pas diviser par zéro."); + } else { + return 2 / a; + } +} + +#[cfg(test)] +mod tests { + use super::*; // mise en portée de tout ce qui est dans le module de dessus + + #[test] + #[should_panic] // ce test doit paniquer, s'il panique pas il est raté + fn two_div_fail() { + two_div_by(0); + } +} +</code></pre>