Accéder au contenu principal

Tutoriel sur les tests unitaires en Python

Apprenez ce que sont les tests unitaires, pourquoi ils sont importants et comment vous pouvez les mettre en œuvre à l'aide de Python.
Actualisé 16 mars 2025  · 10 min de lecture

Les tests unitaires sont une méthode de test des logiciels par laquelle des unités individuelles de code source sont soumises à divers tests afin de déterminer si elles sont aptes à être utilisées. Il détermine et assure la qualité de votre code.

En général, lorsque le processus de développement est terminé, le développeur code les critères, ou les résultats qui sont connus pour être potentiellement pratiques et utiles, dans le script de test pour vérifier l'exactitude d'une unité particulière. Au cours de l'exécution des cas de test, divers cadres enregistrent les tests qui échouent à un critère quelconque et les signalent dans un résumé.

Les développeurs sont censés rédiger des scripts de test automatisés, qui garantissent que chaque section ou unité est conforme à sa conception et se comporte comme prévu.

Tests unitaires Python

Bien que l'écriture de tests manuels pour votre code soit définitivement une tâche fastidieuse et chronophage, le cadre de test unitaire intégré à Python a rendu la vie beaucoup plus facile.

Le cadre de test unitaire de Python s'appelle unittest et est fourni avec Python.

Les tests unitaires permettent à votre code d'être à l'épreuve du temps puisque vous anticipez les cas où votre code pourrait potentiellement échouer ou produire un bogue. Bien que vous ne puissiez pas prévoir tous les cas, vous pouvez néanmoins traiter la plupart d'entre eux.

Une unité peut être classée en plusieurs catégories :

  • Un module entier,
  • Une fonction individuelle,
  • Une interface complète comme une classe ou une méthode.

La meilleure façon d'écrire des tests unitaires pour votre code est de commencer par la plus petite unité testable que votre code puisse avoir, puis de passer à d'autres unités et de voir comment cette plus petite unité interagit avec d'autres unités, de cette façon vous pouvez construire un test unitaire complet pour vos applications.

Le cadre de test unitaire de Python a été inspiré par le cadre de test unitaire de Java ( JUnit ) et présente des caractéristiques similaires à celles des principaux cadres de test unitaire d'autres langages. Le cadre de test unitaire de Python offre diverses fonctionnalitésnotamment :

  • Automatisation des tests
  • Partage du code d'installation et d'arrêt pour les tests
  • Agrégation des tests en collections
  • Indépendance des tests par rapport au cadre de présentation des rapports

Prenons maintenant un exemple et comprenons pourquoi vous avez besoin de tester votre code à l'unité.

Premiers pas avec Python unittest

Vous trouverez ci-dessous les étapes nécessaires à l'utilisation du cadre de Python unittest.

Création d'une fonction cube

Ecrivons un code pour calculer le volume d'un cube en Python

def cuboid_volume(l):
    return (l*l*l)
length = [2,1.1, -2.5, 2j, 'two']
for i in range(len(length)):
    print ("The volume of cuboid:",cuboid_volume(length[i]))
The volume of cuboid: 8
The volume of cuboid: 1.3310000000000004
The volume of cuboid: -15.625
The volume of cuboid: (-0-8j)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-67e1c37a435f> in <module>
      1 for i in range(len(length)):
----> 2     print ("The volume of cuboid:",cuboid_volume(length[i]))
<ipython-input-2-f50464fd88da> in cuboid_volume(l)
      1 def cuboid_volume(l):
----> 2     return (l*l*l)
TypeError: can't multiply sequence by non-int of type 'str'

Analyse des résultats

Le résultat ci-dessus devrait vous donner une idée de l'importance de la mise en place d'un test unitaire pour votre code. Il y a trois choses qui sont certainement incorrectes dans le code ci-dessus :

  • Tout d'abord, le volume du parallélépipède est négatif,
  • Deuxièmement, le volume du cuboïde est un nombre complexe,
  • Enfin, le code aboutit à TypeError car vous ne pouvez pas multiplier une chaîne de caractères, qui n'est pas un indice.

Le troisième problème s'est heureusement soldé par une erreur, tandis que le premier et le deuxième ont réussi, bien que le volume du cuboïde ne puisse pas être négatif et qu'il s'agisse d'un nombre complexe.

Les tests unitaires sont généralement écrits sous la forme d'un code séparé dans un fichier différent, et il peut exister différentes conventions de dénomination que vous pouvez suivre. Vous pouvez écrire le nom du fichier de test unitaire sous la forme name of the code/unit + test séparé par un trait de soulignement ou test + name of the code/unit séparé par un trait de soulignement.

Par exemple, disons que le nom du fichier de code ci-dessus est cuboid_volume.py, alors le nom du code de votre test unitaire pourrait être cuboid_volume_test.py

Sans plus attendre, écrivons le test unitaire pour le code ci-dessus.

Utilisation de assertAlmostEqual

Tout d'abord, créons un fichier Python avec le nom volume_cuboid.py, qui contiendra le code de calcul du volume et le second avec le nom test_volume_cuboid.py, qui contiendra le code de test unitaire.

importation unittest

La classe TestCuboid hérite du module unittest, et dans cette classe, vous définissez diverses méthodes que vous voulez que votre test unitaire vérifie avec votre fonction cuboid_volume.

La première fonction que vous définirez est test_volume, qui vérifiera si la sortie de votre cuboid_volume est égale à ce que vous attendez. Pour ce faire, vous utiliserez la méthode assertAlmostEqual.

Test 1

class TestCuboid(unittest.TestCase):
    def test_volume(self):
        self.assertAlmostEqual(cuboid_volume(2),8)
        self.assertAlmostEqual(cuboid_volume(1),1)
        self.assertAlmostEqual(cuboid_volume(0),0)
        self.assertAlmostEqual(cuboid_volume(5.5),166.375)

code 1

code 2

Exécutons le script ci-dessus. Vous pouvez exécuter le module unittest en tant que script en spécifiant -m lors de son exécution.

!python -m unittest test_volume_cuboid.py

Sortie :

.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK

C'est très bien ! Vous avez donc réussi à faire fonctionner votre premier code de test unitaire.

Le test s'est déroulé avec succès et a retourné OK, ce qui signifie que la fonction cuboid_volume fonctionne comme vous vous y attendez.

Test 2

Voyons ce qui se passe lorsque l'une des méthodes assertAlmostEqual échoue.

code 3

Remarquez que la dernière instruction assert a été modifiée.

!python -m unittest test_volume_cuboid.py

Sortie :

F
======================================================================
FAIL: test_volume (test_volume_cuboid.TestCuboid)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\hda3kor\Documents\Unit_Testing_Python\test_volume_cuboid.py", line 15, in test_volume
    self.assertAlmostEqual(cuboid_volume(5.5),0)
AssertionError: 166.375 != 0 within 7 places (166.375 difference)
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=1)

D'après la sortie ci-dessus, vous pouvez observer que la dernière instruction assert a donné lieu à un AssertionError, et donc à un échec du test unitaire. Le module de test unitaire de Python vous indique la raison de l'échec, ainsi que le nombre d'échecs de votre code.

Utilisation de assertRaises

Examinons maintenant une autre méthode d'affirmation, à savoir assertRaises, qui vous aidera à déterminer si votre fonction cuboid_volume traite correctement les valeurs d'entrée.

Supposons que vous souhaitiez tester si votre fonction cuboid_volume gère la classe ou le type d'entrée. Par exemple, si vous passez une chaîne de caractères en entrée, la fonction traitera-t-elle cette entrée comme une exception ou avec une condition if, puisque la longueur du cuboïde ne peut jamais être une chaîne de caractères.

code 4

!python -m unittest test_volume_cuboid.py

Sortie :

F.
======================================================================
FAIL: test_input_value (test_volume_cuboid.TestCuboid)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\hda3kor\Documents\Unit_Testing_Python\test_volume_cuboid.py", line 17, in test_input_value
    self.assertRaises(TypeError, cuboid_volume, True)
AssertionError: TypeError not raised by cuboid_volume
----------------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (failures=1)

C'est très bien ! Il est donc évident que votre code volume_cuboid.py ne prend pas correctement en compte les données qui lui sont transmises.

Modifier la fonction cube

Ajoutons une condition dans volume_cuboid.py pour vérifier si l'entrée ou la longueur du cuboïde est un booléen ou une chaîne de caractères et soulever une erreur.

code 5

!python -m unittest test_volume_cuboid.py

Sortie :

..
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK

Exécution du script de test Python dans le laboratoire Jupyter

Exécutons maintenant le script de test dans le laboratoire jupyter. Pour ce faire, vous devez d'abord définir le script de test dans le laboratoire jupyter, comme indiqué ci-dessous.

# -*- coding: utf-8 -*-
"""
Created on Sat Apr 25 20:16:58 2020
@author: Aditya
"""
from volume_cuboid import *
import unittest
class TestCuboid(unittest.TestCase):
    def test_volume(self):
        self.assertAlmostEqual(cuboid_volume(2),8)
        self.assertAlmostEqual(cuboid_volume(1),1)
        self.assertAlmostEqual(cuboid_volume(0),1)
    def test_input_value(self):
        self.assertRaises(TypeError, cuboid_volume, True)

Ensuite, vous utiliserez la méthode unittest.main() pour exécuter le script de test, vous pouvez passer plusieurs arguments à la méthode ci-dessous, dont l'un est verbosity level.

Expérimentons différents niveaux de verbosité et voyons comment cela modifie la description de la sortie.

Verbosité 0

unittest.main(argv=[''],verbosity=0, exit=False)
Output:
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
<unittest.main.TestProgram at 0x1de02774348>

Verbosité 1

unittest.main(argv=[''],verbosity=1, exit=False)
Output:
..
----------------------------------------------------------------------
Ran 2 tests in 0.002s
OK
<unittest.main.TestProgram at 0x1de027a1cc8>

Verbosité 2

unittest.main(argv=[''],verbosity=2, exit=False)
Output:
test_input_value (__main__.TestCuboid) ... ok
test_volume (__main__.TestCuboid) ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.002s
OK
<unittest.main.TestProgram at 0x1de027a8308>

Visualisation de l'erreur d'assertion

Enfin, modifions le site final assertAlmostEqual dans la méthode test_volume et analysons comment le niveau de verbosité 2 montrera l'échec de la méthode.

# -*- coding: utf-8 -*-
"""
Created on Sat Apr 25 20:16:58 2020
@author: Aditya
"""
from volume_cuboid import *
import unittest
class TestCuboid(unittest.TestCase):
    def test_volume(self):
        self.assertAlmostEqual(cuboid_volume(2),8)
        self.assertAlmostEqual(cuboid_volume(1),1)
        self.assertAlmostEqual(cuboid_volume(0),1)
    def test_input_value(self):
        self.assertRaises(TypeError, cuboid_volume, True)
unittest.main(argv=[''],verbosity=2, exit=False)

Sortie :

test_input_value (__main__.TestCuboid) ... ok
test_volume (__main__.TestCuboid) ... FAIL
======================================================================
FAIL: test_volume (__main__.TestCuboid)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython-input-28-46ad33b909ee>", line 14, in test_volume
    self.assertAlmostEqual(cuboid_volume(0),1)
AssertionError: 0 != 1 within 7 places (1 difference)
----------------------------------------------------------------------
Ran 2 tests in 0.003s
FAILED (failures=1)
<unittest.main.TestProgram at 0x1de027b5448>

Résumé

Les résultats ci-dessus permettent de tirer les conclusions suivantes :

  • Le niveau de verbosité 0 indique simplement le nombre de tests effectués, c'est-à-dire 2 tests et le temps nécessaire à leur exécution,
  • Niveau de verbosité 1 ajouter deux points .. ce qui signifie que deux tests ont été exécutés,
  • Le niveau de verbosité 2 montre les noms détaillés des méthodes qui ont été exécutées ainsi que leur état OK ou FAIL.

Méthodes d'affirmation disponibles pour unittest

Le module de test unitaire de Python contient de nombreuses méthodes d'affirmation qui peuvent être utilisées pour vos tests.

Méthodes d'affirmation couramment utilisées

Méthodes d'affirmation couramment utilisées

Source : documentation unittest

 Contrôles de production

Les méthodes suivantes vous permettent de vérifier la production d'exceptions, d'avertissements et de messages de journal.

Contrôles de production

Source : documentation unittest

 Méthodes spécifiques aux tâches

Méthodes spécifiques aux tâches

Source : documentation unittest

 

Pour connaître en détail les méthodes de assert, consultez la documentation officielle de Python.

Vous pouvez également apprendre à les connaître à l'aide du module Pydoc, qui est similaire à une fonction help en Python. Vous trouverez ci-dessous une démonstration de la manière dont vous pouvez utiliser le module Pydoc pour consulter la documentation de la méthode assertCountEqual.

!python -m pydoc unittest.TestCase.assertCountEqual

Sortie :

Help on function assertCountEqual in unittest.TestCase:
unittest.TestCase.assertCountEqual = assertCountEqual(self, first, second, msg=None)
    An unordered sequence comparison asserting that the same elements,
    regardless of order.  If the same element occurs more than once,
    it verifies that the elements occur the same number of times.
        self.assertEqual(Counter(list(first)),
                         Counter(list(second)))
     Example:
        - [0, 1, 1] and [1, 0, 1] compare equal.
        - [0, 0, 1] and [0, 1] compare unequal.

Conclusion

Ce tutoriel était une introduction de base aux tests unitaires en Python et à leur importance en tant que développeur. Un bon exercice pour vous serait d'écrire un module de test unitaire pour l'un de vos anciens projets. Cela vous permettra d'acquérir une bonne expérience pratique de l'écriture de tests unitaires. Essayez également d'explorer les autres méthodes Assert. Pour en savoir plus sur les tests unitaires, consultez notre tutoriel Pytest.

Si vous débutez en Python et que vous souhaitez en savoir plus, suivez notre Introduction à la science des données en Python cours d'introduction à la science des données en Python.

Devenez développeur Python

Acquérir les compétences de programmation dont tous les développeurs Python ont besoin.
Commencez à apprendre gratuitement

Abid Ali Awan's photo
Author
Abid Ali Awan
LinkedIn
Twitter

En tant que data scientist certifié, je suis passionné par l'utilisation des technologies de pointe pour créer des applications innovantes d'apprentissage automatique. Avec une solide expérience en reconnaissance vocale, en analyse de données et en reporting, en MLOps, en IA conversationnelle et en NLP, j'ai affiné mes compétences dans le développement de systèmes intelligents qui peuvent avoir un impact réel. En plus de mon expertise technique, je suis également un communicateur compétent, doué pour distiller des concepts complexes dans un langage clair et concis. En conséquence, je suis devenu un blogueur recherché dans le domaine de la science des données, partageant mes idées et mes expériences avec une communauté grandissante de professionnels des données. Actuellement, je me concentre sur la création et l'édition de contenu, en travaillant avec de grands modèles linguistiques pour développer un contenu puissant et attrayant qui peut aider les entreprises et les particuliers à tirer le meilleur parti de leurs données.

Sujets

Apprenez-en plus sur Python avec ces cours !

Certification disponible

Cours

Introduction à Python

4 hr
6.1M
Maîtrisez les bases de l'analyse de données avec Python en seulement quatre heures. Ce cours en ligne vous présentera l'interface Python et explorera les packages populaires.
Afficher les détailsRight Arrow
Commencer le cours
Voir plusRight Arrow