Python - test unitaire
Préambule : toute fonction Python n’a pas vocation à accueillir des tests unitaires.
Les tests unitaires ne sont utiles que pour des fonctions "outils", pas pour des codes complexes avec mes milliers de paramètres.
Débuter les tests unitaires
Principe
Le test unitaire consiste à tester le comportement d’une fonction pour s’assurer que pour une entrée donnée, le résultat donne bien la sortie attendue.
Cela permet notamment de s’assurer de la non-regression (qu’une modification dans le code ne va pas créer une erreur qui se propage dans un code existant).
Installation
Ici, j’utilise le paquet converage.py (https://coverage.readthedocs.io/en/coverage-5.0.4/index.html)
$ pip3 install coverage
Utilisation
Intro Ici, le test va s’effectuer automatiquement, sans que l’on ait à préciser le nom des fichiers : l’avantage est que cela permet d’avoir plusieurs fichiers tests/test_monmodule1.py assez petit et donc qu’il est facile de s’y retrouver.
L’inconvénient est que l’on n’a pas la main sur tout...
Remarque : Il faut se placer dans le dossier ./tests (si on y a mis ses tests)
* Avant de lancer le test, il faut s’assurer qu’il n’y ait pas d’anciennes données, sans quoi le test risque de se faire dedans aussi, ce qui ne marchera pas !
$ coverage erase
* Lancer le test, avec une détection automatique des fichiers sources
$ python3 --branch -m unittest discover
* Créer le rapport
$ coverage report
* Créer une copie des sources dans ./tests/Annotate et y mettre les annotations d’utilisation
$ coverage annotate -d ./Annotate
Test et gitlab
Intégration continue
Extrait du .gitlab-ci.yml
test:
stage: test
script:
- echo "Testing..."
- pip3 install .[test]
- cd tests && coverage erase
- coverage run -m unittest discover
- coverage report
- coverage xml
- sed -i 's|" filename="|" filename="./|g' coverage.xml
coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/'
artifacts:
paths:
- tests/coverage.xml
reports:
coverage_report:
coverage_format: cobertura
path: tests/coverage.xml
Quelques remarques :
* Ici, les modules pour le test sont précisé dans extra_requires/doc du fichier setup.cfg
* Je ne pourrais pas dire à quoi servent individuellement toutes ces lignes (en particulier le sed, et les balises "coverage" et "artifacts", mais visiblement, elles sont nécessaires. Quand je saurais, j’éditerais cet article.
Ajout d’un badge dans Gitlab
Parceque c’est inutile, donc indispensable, mais tout de même plus joli ^^
(sans compter que ça donne mauvaise conscience d’avoir un mauvais rating...)
Il se présente sous la forme :

Et on peut avoir le lien directement en allant dans :
`project > settings > CI/CD > General Pipelines [expand] > Pipeline Status
Ressources
* Visualisation dans Gitlab : https://docs.gitlab.com/ee/ci/testing/test_coverage_visualization.html
* Inclure à la doc Sphinx : https://stackoverflow.com/questions/65944916/how-to-use-sphixs-sphinx-ext-coverages-coverage-show-missing-items https://www.sphinx-doc.org/ar/master/usage/extensions/coverage.html
* https://gricad-gitlab.univ-grenoble-alpes.fr/continuous-everything/ci
* https://docs.gitlab.com/ee/ci/testing/test_coverage_visualization.html#python-example