Comptage de requêtes: test de base des performances Django

Bonjour à tous. Nous avons préparé une traduction d'un autre matériel utile pour les étudiants du cours "Développeur Web en Python" , qui a commencé hier.





Vous pouvez souvent entendre parler des méthodes de test telles que TDD et comment tester la logique métier d'une application. Cependant, tester les performances des applications est une tâche complètement différente. Il existe de nombreuses façons différentes, mais l'approche la plus courante consiste à créer un environnement dans lequel vous pouvez mener une attaque DDoS sur votre application et observer son comportement. C'est un sujet très intéressant, mais ce n'est pas ce dont je veux parler aujourd'hui. Aujourd'hui, nous allons examiner un test plus simple, que vous pouvez faire en utilisant les tests unitaires Django par défaut: c'est-à-dire tester le nombre de fois où votre application accède à la base de données.

Le test est très simple, et c'est exactement l'aspect qui peut nuire aux performances des applications dans les premiers stades. Cet aspect est le tout premier à être testé lorsque quelque chose commence à fonctionner lentement. La bonne nouvelle est qu'il n'y a qu'une seule chose que vous devez savoir pour écrire des tests de ce type: la méthode assertNumQueries , et elle est assez facile à utiliser. Voici un exemple:

from django.test import TestCase, Client
from django.urls import reverse
from trucks.models import Truck

class TrucksTestCase(TestCase):
    def test_list_trucks_view_performance(self):
        client = Client()

        Truck.objects.create(...)

        with self.assertNumQueries(6):
            response = client.get(reverse("trucks:list_trucks"))

        self.assertEqual(response.context["trucks_list"], 1)

Le code ci-dessus affirme que pendant la visualisation, l' "trucks:list_trucks"application n'accèdera à la base de données que 6 fois. Mais il y a autre chose, notez qu'avant de commencer, nous créons d'abord un nouvel objet Truck, et ensuite nous disons qu'il trucks_listy a au moins un objet dans les données de contexte de la vue . Dans ce type de tests, cela est important, car vous avez besoin d'une garantie que vous ne testez pas sur un ensemble de données vide. Il est important de comprendre qu'il Truckne suffit pas d' instancier une classe . Vous devez vérifier s'il a été inclus dans le contexte. Peut-être que vous filtrez la liste des camions, il est donc probable que votre instance Truckne sera pas incluse dans le résultat.

Après avoir fait tout ce qui précède, nous avons déjà fait des progrès significatifs, mais il y a une autre étape importante qui est facile à oublier. Si nous voulons que nos vues évoluent, nous devons nous assurer que les performances ne diminuent pas à mesure que le nombre d'articles retournés augmente. En fin de compte, nous avons toujours un problème de performances si nous nous tournons vers la base de données non pas 6 fois pour obtenir un élément, mais 106 si nous avons 100 éléments. Nous avons besoin d'un nombre constant d'appels de base de données, qui ne dépendra pas du nombre d'articles retournés. Heureusement, ce problème est également résolu très simplement, nous devons ajouter un ou plusieurs éléments à la base de données et compter à nouveau le nombre de hits. Voici à quoi ressemblera le test dans la version finale:

from django.test import TestCase, Client
from django.urls import reverse
from trucks.models import Truck

class TrucksTestCase(TestCase):
    def test_list_trucks_view_performance(self):
        client = Client()

        Truck.objects.create(...)

        with self.assertNumQueries(6):
            response = client.get(reverse("trucks:list_trucks"))

        self.assertEqual(response.context["trucks_list"], 1)

        Truck.objects.create(...)

        with self.assertNumQueries(6):
            response = client.get(reverse("trucks:list_trucks"))

        self.assertEqual(response.context["trucks_list"], 2)

Notez que nous vérifions à nouveau le nombre d'articles retournés dans le contexte, mais lors de la deuxième manche, nous nous attendons à 2 camions ( Truck). La raison de ce comportement est similaire au premier cas.

Assurer un nombre constant d'appels à la base de données lors de l'ajout de nouvelles données est plus prioritaire que d'assurer un petit nombre d'appels en général.

La dernière chose à faire est de vous assurer que vos données sont aussi hydratées que possible. Cela signifie que vous devez créer des données connexes qui seront utilisées lors du traitement de votre vue. Si vous ne le faites pas, il y a un risque que votre application accède à la base de données plus souvent en production qu'en test (bien qu'elle puisse réussir). Dans notre exemple, nous devions créer TruckDriverune entreprise pour notreTruck.

from trucks.models import Truck, TruckDriver
...
        truck = Truck.objects.create(...)
        TruckDriver.objects.create(name="Alex", truck=truck)

Si le nombre d'appels de base de données n'est plus constant après avoir effectué les étapes décrites ci-dessus, recherchez plus d'informations sur les méthodes select_related et prefetch_related .

C'est tout pour aujourd'hui, j'espère qu'à partir de ce moment vous commencerez à vérifier le nombre de requêtes de votre application pour la base de données au tout début du projet. Cela ne prendra pas beaucoup de temps, mais évitera les problèmes pouvant survenir avec l'augmentation du nombre d'utilisateurs de votre application.

Au fait, vous pouvez toujours suivre le cours . À plus.

All Articles