Ecrire des tests automatisés

Dans son essai de 1972 “The Humble Programmer”, Edsger W. Dijkstra a dit qu'un “test de programme peut être une manière très efficace de prouver la présence de bogues, mais qu'il est totalement inadéquat pour prouver leur absence”. Mais cela ne veut pas dire que nous ne devrions pas tester notre programme autant que faire se peut !

L'exactitude de nos programmes est le niveau de conformité de notre code par rapport à ce que nous voulons qu'il fasse. Rust est conçu dans un grand souci d'exactitude des programmes, mais l'exactitude est complexe et difficile à confirmer. Le système de type de Rust endosse une grande partie de cette charge, mais le système de type ne peut pas détecter tous les genres d'erreurs. Ainsi, Rust embarque des fonctionnalités pour écrire des tests automatisés de logiciels à l'intérieur du langage.

Par exemple, imaginons que nous écrivons une fonction ajouter_deux qui ajoute 2 à n'importe quel nombre qu'on lui envoie. La signature de cette fonction prend un entier en paramètre et retourne un entier comme résultat. Lorsque nous implémentons et compilons cette fonction, Rust fait toutes les vérifications de type et d'emprunt que vous avez apprises précédemment afin de s'assurer que, par exemple, nous ne passions pas une valeur de type String ou une référence invalide à cette fonction. Mais Rust ne peut pas vérifier que cette fonction va faire précisément ce que nous avions prévu qu'elle fasse, qui en l'occurence est de retourner le paramètre incrémenté de 2 plutôt que d'ajouter 10 ou d'enlever 50, par exemple ! C'est pour cette situation que les tests sont utiles.

Nous pouvons écrire des tests qui vérifient, par exemple, que lorsque nous donnons 3 à la fonction ajouter_deux, elle retourne bien 5. Nous pouvons lancer ces tests à chaque fois que nous modifions notre code pour s'assurer qu'aucun comportement existant et satisfaisant n'a changé.

Les tests restent une discipline complexe : bien que nous ne puissions couvrir chaque détail sur l'écriture de bons tests en un seul chapitre, nous allons découvrir les mécanismes des moyens de test de Rust. Nous allons voir les annotations et les macros que vous pourrez utiliser lorsque vous écrirez vos tests, le comportement par défaut et les options disponibles pour lancer vos tests, et comment organiser les tests en tests unitaires et tests d'intégration.