Accueil / Blog / Métier / 2015 / Optimiser ses tests unitaires Django avec setUpTestData

Optimiser ses tests unitaires Django avec setUpTestData

Par Yann Fouillat — publié 22/06/2015, édité le 25/06/2015
Découvrez comment gagner en efficacité sur les tests unitaires avec Django 1.8 et sa nouvelle méthode d'initialisation des tests : setUpTestData.
Optimiser ses tests unitaires Django avec setUpTestData

Django intègre dans sa dernière version stable (1.8) une nouvelle méthode permettant de créer les données une seul fois pour tout une série de tests : setUpTestData. Nous avons ainsi pu passer de 180 secondes à 90 secondes en mettant nos tests à jours sur un de nos projet. Nous allons voir ici comment utiliser et mettre en place cette fonctionnalité sur de nouveaux tests ou même des tests déjà existants.

Partons du modèle suivant :

class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)

Et des tests suivants, écris à la manière de Django 1.7 :

class PersonTest(TestCase):
    def setUp(self):
        self.alice = Person.objects.create(first_name='Alice', last_name='Smith')
        self.bob = Person.objects.create(first_name='Bob', last_name='Smith')

    def test_alice_first_name(self):
        self.assertEqual(self.alice.first_name, 'Alice')

    def test_bob_first_name(self):
        self.assertEqual(self.bob.first_name, 'Bob')

    def test_bob_first_name_modified(self):
      self.bob.first_name = 'Jack'
        self.bob.save()
        self.assertEqual(self.bob.first_name, 'Jack')

Nous avons donc deux requêtes exécutées avant chaque test. Ce qui nous fais un total de six requêtes effectuées juste pour créer les donnés nécessaires aux tests. setUpTestData utilise les fonctionnalités des transactions des bases de données et nous permettrais de n'exécuter les requêtes qu'une seul fois pour tout les tests. setUpTestData est une méthode de classe et son utilisation est donc un peu différente de setUp :

class PersonTest(TestCase):
@classmethod
    def setUpTestData(cls):
        cls.alice = Person.objects.create(first_name='Alice', last_name='Smith')
        cls.bob = Person.objects.create(first_name='Bob', last_name='Smith')

    def test_alice_first_name(self):
        self.assertEqual(self.alice.first_name, 'Alice')

    def test_bob_first_name(self):
        self.assertEqual(self.bob.first_name, 'Bob')

    def test_bob_first_name_modified(self):
      self.bob.first_name = 'Jack'
        self.bob.save()
        self.assertEqual(self.bob.first_name, 'Jack')

Les requêtes de création ne seront donc désormais exécutées qu'une seul fois. Mais il reste un autre problème. Si nous faisons tourner les tests tels quels, nous nous rendrions compte que self.bob reste modifié après le test test_bob_first_name_modified. Ceci est du au fait que l'objet self.bob est modifié en mémoire et n'est pas restauré après le test. Nous pouvons faire en sorte de recharger les objet avant chaque test à l'aide de setUp et d'une autre nouvelle fonctionnalité de Django 1.8 : refresh_from_db.

class PersonTest(TestCase):
@classmethod
    def setUpTestData(cls):
        cls.alice = Person.objects.create(first_name='Alice', last_name='Smith')
        cls.bob = Person.objects.create(first_name='Bob', last_name='Smith')

def setUp(self):
self.alice.refresh_from_db()
        self.bob.refresh_from_db()

    def test_alice_first_name(self):
        self.assertEqual(self.alice.first_name, 'Alice')

    def test_bob_first_name(self):
        self.assertEqual(self.bob.first_name, 'Bob')

    def test_bob_first_name_modified(self):
     self.bob.first_name = 'Jack'
        self.bob.save()
        self.assertEqual(self.bob.first_name, 'Jack')

Même si cela fait deux requêtes en plus à chaque test, ce sont des opérations de lecture et non d'écriture, et donc beaucoup plus rapide.

Il est finalement très simple de mettre en place cette nouvelle fonctionnalité, que ce soit pour de nouveaux tests ou d'anciens, permettant un gain de temps assez important.

ABONNEZ-VOUS À LA NEWSLETTER !
Voir aussi
Accéder à sa base de données PostgreSQL depuis QGis ou pgAdmin de manière sécurisée Accéder à sa base de données PostgreSQL depuis QGis ou pgAdmin de manière sécurisée 30/12/2020

Comment interconnecter ses outils de travail sans mettre en péril la sécurité du système ...

La Haute-Garonne met à l’honneur l’application Geotrek dans son magazine 08/06/2021

Le magazine Haute-Garonne du mois de mai-juin 2021 présente le site marando.haute-garonne.fr

Comment migrer vers une version récente de Django ? Comment migrer vers une version récente de Django ? 15/04/2021

Que ce soit pour avoir les dernières fonctionnalités ou les correctifs de sécurité, rester sur ...

Inscrivez-vous à notre prochaine formation d'initiation au Python Scientifique Inscrivez-vous à notre prochaine formation d'initiation au Python Scientifique 22/03/2021

Du 29 au 31 mars, nous ouvrons une session de formation à distance «Introduction au Python ...

Créer un tag d'inclusion avec paramètres dans Django 22/12/2020

La bibliothèque de tags interne permet d'enregistrer des tags avec paramètres ou des tags ...