1A.soft - Tests unitaires, setup et ingéniérie logicielle#

Links: notebook, html, python, slides, GitHub

On vérifie toujours qu’un code fonctionne quand on l’écrit mais cela ne veut pas dire qu’il continuera à fonctionner à l’avenir. La robustesse d’un code vient de tout ce qu’on fait autour pour s’assurer qu’il continue d’exécuter correctement.

from jyquickhelper import add_notebook_menu
add_notebook_menu()
from pyensae.graphhelper import draw_diagram

Petite histoire#

Supposons que vous ayez implémenté trois fonctions qui dépendent les unes des autres. la fonction f3 utilise les fonctions f1 et f2.

draw_diagram("blockdiag { f0 -> f1 -> f3; f2 -> f3;}")
../_images/td1a_unit_test_ci_4_0.png

Six mois plus tard, vous créez une fonction f5 qui appelle une fonction f4 et la fonction f2.

draw_diagram('blockdiag { f0 -> f1 -> f3; f2 -> f3; f2 -> f5 [color="red"]; f4 -> f5 [color="red"]; }')
../_images/td1a_unit_test_ci_6_0.png

Ah au fait, ce faisant, vous modifiez la fonction f2 et vous avez un peu oublié ce que faisait la fonction f3… Bref, vous ne savez pas si la fonction f3 sera impactée par la modification introduite dans la fonction f2 ? C’est ce type de problème qu’on rencontre tous les jours quand on écrit un logiciel à plusieurs et sur une longue durée. Ce notebook présente les briques classiques pour s’assurer de la robustesse d’un logiciel.

  • les tests unitaires

  • un logiciel de suivi de source

  • calcul de couverture

  • l’intégration continue

  • écrire un setup

  • écrire la documentation

  • publier sur PyPi

Ecrire une fonction#

N’importe quel fonction qui fait un calcul, par exemple une fonction qui résoud une équation du second degré.

def solve_polynom(a, b, c):
    # ....
    return None

Ecrire un test unitaire#

Un test unitaire est une fonction qui s’assure qu’une autre fonction retourne bien le résultat souhaité. Le plus simple est d’utiliser le module standard unittest et de quitter les notebooks pour utiliser des fichiers. Parmi les autres alternatives : pytest et nose.

Couverture ou coverage#

La couverture de code est l’ensemble des lignes exécutées par les tests unitaires. Cela ne signifie pas toujours qu’elles soient correctes mais seulement qu’elles ont été exécutées une ou plusieurs sans provoquer d’erreur. Le module le plus simple est coverage. Il produit des rapports de ce type : mlstatpy/coverage.

Créer un compte GitHub#

GitHub est un site qui contient la majorité des codes des projets open-source. Il faut créer un compte si vous n’en avez pas, c’est gratuit pour les projets open souce, puis créer un projet et enfin y insérer votre projet. Votre ordinateur a besoin de :

Vous pouvez lire GitHub Pour les Nuls : Pas de Panique, Lancez-Vous ! (Première Partie) et bien sûr faire plein de recherches internet.

Note

Tout ce que vous mettez sur GitHub pour un projet open-source est en accès libre. Veillez à ne rien mettre de personnel. Un compte GitHub fait aussi partie des choses qu’un recruteur ira regarder en premier.

Intégration continue#

L’intégration continue a pour objectif de réduire le temps entre une modification et sa mise en production. Typiquement, un développeur fait une modification, une machine exécute tous les tests unitaires. On en déduit que le logiciel fonctionne sous tous les angles, on peut sans crainte le mettre à disposition des utilisateurs. Si je résume, l’intégration continue consiste à lancer une batterie de tests dès qu’une modification est détectée. Si tout fonctionne, le logiciel est construit et prêt à être partagé ou déployé si c’est un site web.

Là encore pour des projets open-source, il est possible de trouver des sites qui offre ce service gratuitement :

A part GitLab-ci, ces trois services font tourner les tests unitaires sur des machines hébergés par chacun des sociétés. Il faut s’enregistrer sur le site, définir un fichier .travis.yml, .appveyor.yml ou circle.yml puis activer le projet sur le site correspondant. Quelques exemples sont disponibles à pyquickhelper ou scikit-learn. Le fichier doit être ajouté au projet sur GitHub et activé sur le site d’intégration continue choisi. La moindre modification déclenchera un nouveau build.permet

La plupart des sites permettent l’insertion de badge de façon à signifier que le build fonctionne.

from IPython.display import Image
try:
    im = Image("https://travis-ci.com/sdpython/ensae_teaching_cs.png")
except TimeoutError:
    im = None
im
../_images/td1a_unit_test_ci_17_0.png
from IPython.display import SVG
try:
    im = SVG("https://codecov.io/github/sdpython/ensae_teaching_cs/coverage.svg")
except TimeoutError:
    im = None
im
../_images/td1a_unit_test_ci_18_0.svg

Il y a des badges un peu pour tout.

Ecrire un setup#

Le fichier setup.py détermin la façon dont le module python doit être installé pour un utilisateur qui ne l’a pas développé. Comment construire un setup : setup.

Ecrire la documentation#

L’outil est le plus utilisé est sphinx. Saurez-vous l’utiliser ?

Dernière étape : PyPi#

PyPi est un serveur qui permet de mettre un module à la disposition de tout le monde. Il suffit d’uploader le module… Packaging and Distributing Projects ou How to submit a package to PyPI. PyPi permet aussi l’insertion de badge.

try:
    im = SVG("https://badge.fury.io/py/ensae_teaching_cs.svg")
except TimeoutError:
    im = None
im
../_images/td1a_unit_test_ci_25_0.svg