Gestion des fixtures dans Python unittest : Différences entre setUp et setUpClass

Dans l'écosystème Python, le module unittest est l'outil standard pour structurer les tests unitaires. Une notion fondamentale pour garantir l'indépendance des tests est celle des "fixtures". Celles-ci permettent de préparer l'environnement avant l'exécution d'un test et de le nettoyer après.

Fixtures au niveau de l'instance : setUp et tearDown

Par défaut, lorsqu'une classe hérite de unittest.TestCase, elle peut définir les méthodes setUp() et tearDown(). Ces méthodes sont appelées systématiquement avant et après chaque méthode de test (toute méthode commençant par le préfixe test_).

import unittest

class TestFileProcessing(unittest.TestCase):
    def setUp(self):
        # Cette méthode s'exécute avant chaque test
        print("\n--- Création d'un fichier temporaire ---")
        self.temp_file = "data.tmp"

    def tearDown(self):
        # Cette méthode s'exécute après chaque test
        print("--- Suppression du fichier temporaire ---")
        self.temp_file = None

    def test_write_operation(self):
        print("Action : Test de l'écriture de données.")

    def test_read_operation(self):
        print("Action : Test de la lecture de données.")

if __name__ == '__main__':
    unittest.main()

Dans l'exemple ci-dessus, si vous avez dix méthodes de test, le fichier temporaire sera créé et supprimé dix fois. Bien que cela garantisse une isolation parfaitte, cette approche devient problématique lorsque l'initialisasion est coûteuse en ressources (connexion à une base de données distante, initialisation d'un navigateur Web via Selenium, etc.).

Fixtures au niveau de la classe : setUpClass et tearDownClass

Pour optimiser les performances et éviter les répétitions inutiles, unittest propose les méthodes setUpClass() et tearDownClass(). Celles-ci ne sont exécutées qu'une seule fois pour l'ensemble de la classe de test.

Il est impératif de noter deux contraintes technqiues :

  • Elles doivent être décorées avec @classmethod.
  • Elles prennent l'argument cls (la classe elle-même) au lieu de self.
import unittest

class TestAPIService(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        # Exécuté une seule fois au début
        print(">>> Initialisation de la connexion API Gateway <<<")
        cls.api_token = "ABC-123"

    @classmethod
    def tearDownClass(cls):
        # Exécuté une seule fois à la fin
        print(">>> Déconnexion et destruction de la session API <<<")

    def test_get_user_profile(self):
        print(f"Test : Récupération profil avec jeton {self.api_token}")

    def test_update_settings(self):
        print(f"Test : Mise à jour des paramètres avec jeton {self.api_token}")

if __name__ == '__main__':
    unittest.main()

Tableau récapitulatif des différences

Caractéristique setUp / tearDown setUpClass / tearDownClass
Fréquence Avant/Après chaque test individuel. Une seule fois par classe de test.
Décorateur Aucun. @classmethod obligatoire.
Argument self (instance de la classe). cls (la classe elle-même).
Cas d'usage Nettoyage de variables, reset de petits objets. Connexions DB, chargement de gros fichiers, mocks réseaux.

Étiquettes: Python unittest Unit-Testing Software-Quality

Publié le 5 juin à 22h11