This page was exported from Enseignement de l'informatique et du numérique au lycée Boissy d'Anglas
[ https://icn-isn-boissy.yj.fr/wp ] Export date: Wed Feb 26 11:38:24 2025 / +0000 GMT |
||
Doctest : une façon originale et pratique de tester…Objectifs
MotivationVous savez documenter les fonctions à l'aide d'une «chaîne de documentation» (ou «docstring»), c'est-à-dire une chaîne de caractères placée immédiatement après l'en-tête de la fonction. Voici un tel exemple de documentation
Cette documentation peut être exploitée avec la fonction help :
À faire Utilisez Pyzo pour
Réaliser une telle chaîne de documentation permet
Mais vous allez découvrir que cela permet davantage encore ! Utiliser le module doctestLes exemples donnés dans une chaîne de documentation peuvent être testés à l'aide d'un module de Python nommé doctest. À faire Depuis l'interpréteur (shell), dans lequel la fonction fact ci-dessus est supposée chargée, tapez les deux lignes
pour importer le module, et
Vous devez obtenir >>> doctest.testmod() TestResults(failed=0, attempted=2) La fonction testmod du module doctest est allée chercher dans les docstring des fonctions du module actuellement chargé, c'est-à-dire Et si un exemple et la fonction ne sont pas d'accord ?À faire Modifiez le deuxième exemple, en mettant 121 à la place de 120 dans le second exemple. Chargez le fichier dans l'interpréteur (touche F5) et retapez les deux lignes
Vous devez obtenir >>> doctest.testmod() ********************************************************************** File "/home/eric/AP1/exples_doctest.py", line 24, in __main__.fact Failed example: fact(5) Expected: 121 Got: 120 ********************************************************************** 1 items had failures: 1 of 2 in __main__.fact ***Test Failed*** 1 failures. Qu'est ce que tout cela révèle ?
Lorsqu'il y a de tels échecs, cela invite le programmeur à vérifier son programme, … ou bien les exemples de sa documentation, comme c'est le cas ici. Rendre automatique les testsIl est très facile de rendre automatique les tests et ainsi de ne plus avoir à faire appel explicitement (et manuellement) à la fonction testmod. Il suffit pour cela d'inclure en fin de fichier les trois lignes : if __name__ == '__main__': import doctest doctest.testmod() À faire Ajoutez ces trois lignes à la fin du fichier Que remarquez-vous dans le cas sans erreur ? Rendre les doctests bavards même en cas de succèsUn paramètre optionnel de la fonction testmod permet d'obtenir plus d'informations sur les tests effectués mêmes en cas de succès. Il suffit pour cela de rajouter le paramètre ̀`verbose=True`` : doctest.testmod(verbose = True) À faire Faites-le ! Et observez ce que vous obtenez
Les sorties complexesTester les exemples des docstring avec le module doctest peut être source de déboires et de pièges. Vous allez découvrir certains d'entre eux et les remèdes qu'on peut y apporter. Avec les listesSupposez que vous vouliez donner un exemple qui produit la liste des factorielles des entiers de 0 à 5. Vous avez donc complété votre documentation en ajoutant """ paramètre n : (int) un entier valeur renvoyée : (int) la factorielle de n. CU : n >= 0 Exemples : >>> fact(3) 6 >>> fact(5) 120 La liste des factorielles des entiers de 0 à 5 >>> [fact(n) for n in range(6)] [1,1,2,6,24,120] """ Avertissement La ligne blanche entre le deuxième exemple et la phrase qui suit est absolument nécessaire. En son absence, la phrase sera comprise comme faisant partie de la sortie produite par le deuxième exemple, et le test échouera donc. Il est clair que ce nouvel exemple est tout à fait correct. Pourtant, si vous procédez au test vous constaterez que sur les trois exemples testés, l'un a abouti à un échec : le troisième. À faire Faites-le ! Quel est le problème ? Cela vient du fait que la fonction testmode effectue une comparaison litérale entre la réponse fournie par la documentation (Expected ) et celle fournie par l'interpréteur (Got). À faire Examinez attentivement ces deux points (Expected et Got) dans la réponse du test que vous venez d'effectuer. Avez-vous compris ? Le problème, ce sont les espaces que l'interpréteur place après chaque virgule dans l'énumération des éléments de la liste. Dans la documentation, ils n'y sont pas. Comment corriger ce point ? C'est simple, il faut mettre des espaces entre les éléments d'une liste. Mais ce n'est pas si simple. On peut facilement mettre plusieurs espaces, comme ci-dessous : """ paramètre n : (int) un entier valeur renvoyée : (int) la factorielle de n. CU : n >= 0 Exemples : >>> fact(3) 6 >>> fact(5) 120 La liste des factorielles des entiers de 0 à 5 >>> [fact(n) for n in range(6)] [1, 1, 2, 6, 24, 120] """ À faire Faites-le ! Testez ! L'excès d'espaces provoque des erreurs. Si on ajoute, sous forme d'un commentaire la directive #doctest : + NORMALIZE WHITESPACE , alors le test réussit, à condition néanmoins d'avoir mis au moins une espace après chaque virgule. """ paramètre n : (int) un entier valeur renvoyée : (int) la factorielle de n. CU : n >= 0 Exemples : >>> fact (3) 6 >>> fact (5) 120 La liste des factorielles des entiers de 0 à 5 >>> [fact (n) for n in range (6)] ... # doctest: +NORMALIZE_WHITESPACE [1, 1, 2, 6, 24, 120] """ À faire Vérifiez-le ! Avertissement les trois petits points sous les trois chevrons sont indispensables. Avec la directice supplémentaire +ELLIPSIS , on peut même se dispenser d'énumérer explicitement tous les éléments de la liste : """ paramètre n : (int) un entier valeur renvoyée : (int) la factorielle de n. CU : n >= 0 Exemples : >>> fact(3) 6 >>> fact(5) 120 La liste des factorielles des entiers de 0 à 5 >>> [fact(n) for n in range(6)] ... # doctest: +NORMALIZE_WHITESPACE, +ELLIPSIS [1, ..., 24, 120] """ À faire Vérifiez-le ! Attention aux ensembles et dictionnairesContrairement aux listes ou tuples, les ensembles et les dictionnaires ne sont pas des structures de données séquentielles. Il est impossible de prévoir dans quel ordre un interpréteur Python écrira les éléments de ces structures. Par exemple, on peut très bien avoir >>> {'a', 'b'} {'a', 'b'} comme on peut avoir >>> {'a', 'b'} {'b', 'a'} Il est donc difficile d'illustrer une valeur d'un de ces deux types dans un exemple d'une docstring. Il est préférable de tester l'égalité de deux valeurs [1] : >>> {'a', 'b'} == {'b', 'a'} Voici donc un exemple de ce qu'il est envisageable de placer dans une docstring Un dictionnaire de certaines valeurs de fact : >>> set (n for n in range(5)) == {0, 1, 2, 3, 4} True À faire Vérifiez ce point ! Avec des sorties aléatoiresComment tester des fonctions qui produisent des valeurs aléatoires ? Dans l'absolu, il est impossible de placer un exemple dans la docstring donnant le résultat d'un appel à de telles fonctions puisque les valeurs qu'elles renvoient sont imprévisibles. Par exemple si on veut tester qu'une fonction simulant un dé à six faces ne produit que des nombres compris entre 1 et 6, comment faire ? On peut si on le souhaite vérifier que cette fonction ne renvoie que des nombres compris entre 1 et 6. from random import randrange def de(): """ paramètre : aucun valeur renvoyée : (int) un nombre choisi au hasard compris entre 1 et 6. CU : aucune Exemple : >>> 1 <= de() <= 6 True """ return randrange(1,7) À faire Concevez un test qui vérifie 100 fois qu'aucun nombre produit par la fonction de n'est en dehors de l'intervalle [1,6] . Mais un tel test ne prouve pas que jamais la fonction ne produira un nombre en dehors de cet intervalle. MéthodologieNote Pour chacun des fichiers de programmes Python que vous écrirez durant les séances de TP, ainsi que dans la réalisation du projet de fin de semestre, vous devrez
Pour en savoir plusVoir la documentation de Python. Notes merci à l'université de Lilles pour son cours Algorithmes et Programmation 1.
|
||
Post date: 2019-10-09 12:06:24 Post date GMT: 2019-10-09 10:06:24 Post modified date: 2020-05-18 10:50:55 Post modified date GMT: 2020-05-18 08:50:55 |
||
Powered by [ Universal Post Manager ] plugin. HTML saving format developed by gVectors Team www.gVectors.com |