Python Code Coverage
Python est l’un des langages de programmation les plus populaires actuellement disponibles. En raison de sa nature généraliste, Python trouve une application dans divers cas d’utilisation de développement logiciel allant du simple script aux serveurs web en passant par des frameworks comme Django.
Cependant, comme pour les autres langages de programmation, les tests restent l’un des aspects les plus importants du développement logiciel en Python.
Dans ce post, nous verrons quelques outils pour mesurer et écrire la couverture des cas de test pour le code Python.
Unittest
La bibliothèque standard de Python est préconstruite avec un module nommé unittest. Inspiré par JUnit et d’autres frameworks de tests unitaires des principaux langages de programmation, unittest est un framework de tests qui vous permet d’automatiser les tests, de configurer le code partagé et de l’arrêter pour les tests et plus encore.
L’une des fonctionnalités importantes d’unittest est le test fixture, c’est-à-dire la configuration nécessaire pour exécuter un ou plusieurs tests, et toutes les actions de nettoyage associées. Avec le fixage de texte, les activités, comme la création de bases de données temporaires ou proxy, de répertoires, ou le démarrage d’un processus serveur, peuvent être prises en charge à un seul endroit.
Prenons quelques exemples de cas de test et voyons comment ils sont implémentés en utilisant unittest:
import unittest
classe TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual(‘foo’.upper(), ‘FOO’)
def test_isupper(self):
self.assertTrue(‘FOO’.isupper())
self.assertFalse(‘Foo’.isupper())
def test_split(self):
s = ‘hello world’
self.assertEqual(s.split(), )
# vérifier que s.split échoue lorsque le séparateur n’est pas une chaîne
with self.assertRaises(TypeError):
s.split(2)
if __name__ == ‘__main__’:
unittest.main()
Créer un scénario de test en sous-classant unittest.TestCase. Ensuite, vous pouvez définir des tests individuels avec des méthodes. Notez que les noms des scénarios de test doivent commencer par le mot test. Cette convention de nommage informe le gestionnaire de tests sur les méthodes qui représentent des tests.
Le gestionnaire de tests est le composant qui orchestre l’exécution des tests et fournit le résultat à l’utilisateur. Sa mise en œuvre varie et il peut utiliser une interface graphique, une interface textuelle ou retourner une valeur spéciale pour indiquer les résultats de l’exécution des tests.
Pytest
Pytest est un framework de test Python tiers. Il vise à fournir un cadre pour écrire vos tests efficacement, en supprimant tous les frais généraux pour la création de tests. Pytest est supporté par Python 2.7, 3.4, 3.5, 3.6, Jython, PyPy-2.3 sur Unix/Posix et Windows.
Regardons comment démarrer avec Pytest.Tout d’abord, téléchargez la dernière version et installez-la via pip:
Vous pouvez vérifier la version installée par:
Maintenant, prenons un exemple de fonction et le cas de test associé.
def func(x):
return x + 1def test_answer():
assert func(3) == 5
La fonction func prend une entrée x et retourne une valeur x + 1. Dans le scénario de test, nous affirmons si la fonction func prend l’entrée 3 et renvoie 5. On s’attend à ce que ce scénario de test échoue. Pour exécuter le test, il suffit de taper pytest dans le répertoire qui contient le fichier test_sample.py.
$ pytest
=========================== session de test démarre ============================
plateforme linux – Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
rootdir : $REGENDOC_TMPDIR, inifile:
collected 1 itemtest_sample.py F ================================= FAILURES =================================
_______________________________ test_answer ________________________________
def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)
test_sample.py:5 : AssertionError
========================= 1 failed in 0.12 seconds =========================
Coverage.py
Coverage.py est l’un des outils de couverture de code les plus populaires pour Python. Il utilise les outils d’analyse de code et les crochets de traçage fournis dans la bibliothèque standard de Python pour mesurer la couverture. Il fonctionne sur les principales versions de CPython, PyPy, Jython et IronPython. Vous pouvez utiliser Coverage.py avec unittest et Pytest.
Vous pouvez soit télécharger la dernière version de Coverage et l’installer manuellement, soit l’installer avec pip comme:
Maintenant exécutez votre programme avec coverage comme
Puis pour obtenir des données de couverture, exécutez
Voici un exemple de sortie de données de couverture
Nom Stmts Miss Cover Missing
——————-
my_program.py 20 4 80% 33-35, 39
my_other_module.py 56 6 89% 17-23
——————-
TOTAL 76 10 87%
Générer le rapport en fichier html:
$ coverage html
C’est un exemple de rapport HTML tel que généré par Coverage.py. Il comprend le module, les déclarations, les manquants, les exclus, les branches, les partiels et la couverture.
Pytest-cov
Pytest-cov est un plugin Python pour générer des rapports de couverture. En plus des fonctionnalités supportées par la commande coverage, il supporte également les tests centralisés et distribués. Il prend également en charge la couverture des sous-processus.
Une fois que vous avez écrit des cas de test comme requis avec Pytest, vous pouvez utiliser Pytest-cov pour exécuter tous les tests et rapporter la couverture.
Pour commencer, installez Pytest-cov comme:
Tests centralisés
Les tests centralisés rapportent la couverture combinée du processus principal et de tous ses sous-processus. Vous pouvez exécuter des tests centralisés en utilisant,
Tests distribués
Installer Pytest-xdist, pour le support des systèmes distribués:
Les tests distribués peuvent être effectués dans deux modes, dist réglé sur load et each. Lorsqu’il est réglé sur load, la couverture combinée de tous les esclaves est rapportée pendant le test distribué. Les esclaves peuvent être répartis sur un nombre quelconque d’hôtes et chaque esclave peut être situé n’importe où sur le système de fichiers. Chaque esclave aura ses sous-processus mesurés.
Pour les tests distribués dans chaque mode, pytest-cov rapporte également la couverture combinée de tous les esclaves. Puisque chaque esclave exécute tous les tests, cela permet de générer un rapport de couverture combinée pour plusieurs environnements
Summary
Dans ce post, nous avons appris à connaître divers frameworks de tests unitaires et de couverture de code Python. Bien que ces frameworks facilitent le processus de test, vous devez toujours écrire les tests. Voici quelques bonnes pratiques à considérer lors de l’écriture des tests unitaires.
- Utiliser des noms longs et descriptifs. Cela évite souvent le besoin de doctrines dans les méthodes de test.
- Les tests doivent être isolés. N’interagissez pas avec une base de données ou un réseau réel. Utilisez une base de données de test séparée qui est déchirée ou utilise des objets fantaisie.
- Concentrez-vous sur un minuscule morceau de fonctionnalité.
- Doit être rapide, mais un test lent est mieux que pas de test.
- Il est souvent logique d’avoir une classe de cas de test pour une seule classe ou un seul modèle.