Leçon 8 / 20

Mesurer et interpréter la couverture

25 min Python — typage, tests et performance Gratuit

Objectif : Repérer les lignes et les branches non testées dans la suite de tests de l’outil de dépenses, puis décider quels tests ajouter en fonction du comportement métier.

Une suite de tests peut réussir tout en laissant une partie du service des dépenses sans vérification. Vous avez besoin de savoir quelles lignes sont réellement exécutées et quels chemins conditionnels restent inexplorés avant de considérer le service suffisamment contrôlé.

Dans les leçons précédentes, vous avez construit des tests unitaires, paramétré des cas d’entrée et simulé une dépendance externe. Ici, vous mesurez ce que cette suite exerce effectivement : Coverage.py produit un rapport exploitable pour orienter les prochains tests, sans remplacer l’analyse des règles métier.

Installer et lancer Coverage.py

Coverage.py observe les lignes exécutées pendant une commande Python, puis compare ces lignes avec le code mesurable des fichiers concernés. Depuis la racine du projet, installez l’outil dans l’environnement de développement et exécutez toute la suite de tests sous sa surveillance. La commande ci-dessous ne modifie ni les tests ni le comportement du paquet.

Terminal
python -m pip install coverage
python -m coverage run --source=src/depenses -m pytest
python -m coverage report --show-missing
Résultat attendu
Les tests pytest s’exécutent. Coverage.py affiche ensuite une ligne par module mesuré, avec le nombre d’instructions, celles qui n’ont pas été exécutées et le pourcentage de couverture.

L’option --source=src/depenses limite la mesure au paquet applicatif : les fichiers de tests ne gonflent pas le résultat. L’option --show-missing ajoute les numéros de ligne non exécutés. Les valeurs exactes dépendent de l’état de vos modules et de votre environnement ; ne recopiez donc pas un pourcentage d’exemple comme s’il s’agissait du résultat de votre projet.

Lire les lignes manquantes

La couverture de lignes indique la part des instructions exécutables qui ont été atteintes pendant les tests. Dans le rapport, une colonne Missing ou Missing Lines donne les numéros de ligne absents du parcours mesuré. Si une ligne de validation dans service.py n’apparaît pas dans les tests, vérifiez d’abord quelle règle cette validation représente, puis écrivez un test qui démontre le comportement attendu.

Une ligne manquante n’est pas automatiquement un défaut. Elle peut correspondre à une situation exceptionnelle importante, qu’il faut tester, ou à du code non pertinent pour le périmètre mesuré. Ouvrez le fichier à la ligne indiquée et reliez-la à un cas d’usage concret ; ne rédigez pas un test qui exécute seulement la ligne sans vérifier un résultat utile.

Mesurer aussi les branches

La couverture de lignes ne suffit pas toujours à révéler un parcours incomplet. Une condition peut être évaluée et sa ligne comptée comme exécutée alors qu’un seul de ses résultats possibles a été suivi. La couverture de branches mesure ces sorties distinctes, par exemple le chemin où une collection est vide et celui où elle contient des dépenses.

Terminal
python -m coverage erase
python -m coverage run --branch --source=src/depenses -m pytest
python -m coverage report --show-missing
Résultat attendu
Le rapport affiche les lignes manquantes et, lorsque des branches ne sont pas couvertes, les chemins conditionnels incomplets. La couverture de branches peut être inférieure à la couverture de lignes.

La première commande efface les données précédentes afin que le rapport corresponde uniquement à cette exécution. L’option --branch active la mesure des branches ; gardez-la dans vos mesures habituelles si vous voulez contrôler ces chemins. Le test paramétré déjà présent pour le calcul du total couvre notamment la liste vide, une dépense, plusieurs dépenses et un montant nul : confrontez ces cas aux branches réellement signalées par l’outil.

Prioriser les tests à ajouter

Commencez par examiner les lignes absentes dans la logique métier et les branches qui peuvent modifier un résultat ou empêcher l’enregistrement d’une dépense. Pour chaque chemin important, ajoutez un test dans le fichier adapté, relancez la suite, puis relisez le rapport. Cette boucle permet de vérifier que le nouveau test atteint effectivement le code visé, sans inventer un seuil universel de couverture.

Si un fichier apparaît avec une couverture nulle, vérifiez que le test qui devrait l’exercer est bien lancé et que le chemin source est correct. Pour un test ciblé, vous pouvez aussi exécuter uniquement tests/test_service.py sous Coverage.py, mais ce rapport ne décrit alors que ce sous-ensemble : il ne remplace pas la mesure de toute la suite. Conservez la commande complète pour une vérification globale reproductible.

À retenir

  • Lancez toute la suite avec Coverage.py en ciblant le paquet `src/depenses`.
  • Utilisez `--show-missing` pour localiser les lignes qui ne sont pas exécutées.
  • Activez `--branch` pour repérer les chemins conditionnels non testés.
  • Interprétez les manques selon les règles métier ; le pourcentage seul ne mesure pas la qualité des assertions.
  • Après l’ajout d’un test pertinent, relancez la suite et vérifiez le nouveau rapport.

Dans la prochaine leçon, vous identifierez les opérations d’entrée-sortie qui bloquent le traitement avant de les rendre concurrentes.

Envie d'aller plus loin ?

Les cours Enovatic sont gratuits et le resteront. Si vous cherchez un accompagnement encadré, nos formations professionnelles sont animées par les mêmes formateurs.