Prérequis : cours sur la mise au point des programmes
À l’issue de ce TP, vous saurez :
- utiliser les exceptions pour rendre un programme robuste face aux saisies incorrectes ;
- identifier et corriger des bogues dans un programme existant ;
- écrire des tests unitaires avec
assertet avecpytest; - mesurer et comparer les performances d’un programme à l’aide de
time.perf_counter().
Introduction
Les activités pratiques qui suivent ont pour objectif de vous faire appliquer les notions présentées dans le cours :
- les exceptions ;
- les bogues ;
- les tests unitaires ;
- les performances.
PizzaError
Une pizzeria souhaiterait créer une sorte de drive automatique pour ses clients afin qu’ils puissent commander en ligne une pizza selon les stocks disponibles.
Un stagiaire a déjà commencé l’écriture d’un programme prototype : pizza_drive.py .
Cependant comme vous allez pouvoir le constater, le programme est largement perfectible :
- mauvaise gestion des saisies (caractères VS entier) ;
- commande de pizza malgré les stocks vides ;
- plantage lorsque l’on commande la pizza 3.
À l’aide des exceptions, rendez ce programme plus robuste et plus ergonomique pour le client, c’est à dire sans plantage inopiné.
Chasse aux bogues
- Téléchargez et décompressez l’archive bogues.zip .
- Pour chacun des scripts :
- trouvez l’origine du bogue ;
- proposez un correctif pour le rendre fonctionnel.
Tests unitaires
À votre tour de mettre en œuvre les tests unitaires sur une classe Rectangle à réaliser. Vous utiliserez la méthode simple avec le mot clef assert, puis la librairie pytest dans un second temps.
Classe Rectangle
L’entreprise GEOFORME développe des logiciels et outils de dessin industriel.
Le développeur avant vous dans le service a commencé à développer une classe Rectangle
disponible dans le fichier rectangle.py
. Il a principalement défini l’API de la classe
et positionné des TODO comme ci-dessous dans chaque méthode :
# TODO : compléter le code de la méthode
pass
Si vous détectez des problèmes potentiels, vous pourrez les signaler en levant une
Exception comme ci-dessous :
# Un problème potentiel...
if probleme == True:
raise Exception("Un problème est survenu")
Le responsable du service vous demande de finir de coder cette classe et d’écrire les tests unitaires qui permettront de la valider et de l’intégrer dans le reste du logiciel de dessin industriel.
Concernant les tests unitaires, vous créerez deux versions et donc deux fichiers :
tests_rectangle_assert.py: version avec le mot-clefasserttests_rectangle_pytest.py: version avec la librairiepytest
Optimisation et performances
Chasse aux performances
Johnny Begood participe en ce moment à un challenge algorithmique sur une plate-forme en ligne. Pour le problème n°10, il doit écrire un programme qui affiche le \(2000\text{-ième}\) nombre premier. Il a écrit un code qui fonctionne parfaitement bien (le résultat est \(17~389\)), mais la plate-forme a fixé une limite de temps d’exécution (< 100 ms) pour valider le challenge et son programme est trop lent.
Chronométrage
- Téléchargez son code source : probleme_v00.py .
- À l’aide de la fonction
perf_counter()du moduletime, mesurez et affichez le temps d’exécution de son programme et plus particulièrement de sa fonctionrechercher_nieme_nombre_premier(). - Notez le résultat moyen obtenu sur trois exécutions et confirmez le refus par la plate-forme.
Première optimisation idiomatique
Harry a entendu parlé qu’en Python les boucles for étaient plus performantes que les
boucles while.
- Créer un nouveau script
programme_v02.py, copiez/collez le code de la versionv00et modifiez le code de sa fonctionetre_premier()pour remplacer la bouclewhilepar une bouclefor. - Chronométrez le temps d’exécution obtenu et notez le résultat moyen sur trois lancement. Comparez le temps entre les versions
v00etv02. Est-ce suffisant ?
Seconde optimisation algorithmique
Après avoir lu la page wikipédia consacrée au nombres premiers, il découvre que le plus grand facteur possible pour un nombre non premier N est \(\sqrt{N}\).
- Créez un nouveau script
programme_v03.pyà partir de la précédente version et modifiez la limite de la boucleforde \(n-1\) à \(\sqrt{n}\). - Chronométrez cette nouvelle version comme précédemment et conclure.
Profilage
Effectuez un profilage du script de départ probleme_v00.py et notez les
résultats :
- pour la fonction
rechercher_nieme_nombre_premier():- nombre d’appels ;
- temps moyen d’exécution ;
- temps total d’exécution.
- pour la fonction
etre_premier():- nombre d’appels ;
- temps moyen d’exécution ;
- temps total d’exécution.