# Documentation Django 6.0.7

# Thématiques de tests avancées

## La fabrique de requêtes

class RequestFactory

La classe `RequestFactory` partage la même API que le client de test. Cependant, au lieu de se comporter comme un navigateur, `RequestFactory` offre une manière de générer une instance de requête pouvant être utilisée comme premier paramètre de n’importe quelle vue. Cela permet de tester une fonction de vue de la même façon que vous testeriez toute autre fonction, comme une boîte noire, avec des données connues en entrée et en testant un résultat spécifique.

L’API de `RequestFactory` est un tout petit peu plus restreinte que celle du client de test :

- Elle ne donne accès qu’aux méthodes HTTP `get()`, `post()`, `put()`, `delete()`, `head()`, `options()` et `trace()`.

- Toutes ces méthodes acceptent les mêmes paramètres, à l’exception de `follow`. Comme il ne s’agit que d’une fabrique produisant des requêtes, le traitement de la réponse est de votre responsabilité.

- Elle ne gère pas les intergiciels. Les attributs de session et d’authentification doivent être fournis par le test lui-même, si nécessaire, pour que la vue fonctionne correctement.

### Exemple

L’exemple suivant est un test unitaire utilisant la fabrique de requêtes :

    from django.contrib.auth.models import AnonymousUser, User
    from django.test import RequestFactory, TestCase

    from .views import MyView, my_view

    class SimpleTest(TestCase):
        def setUp(self):
            # Every test needs access to the request factory.
            self.factory = RequestFactory()
            self.user = User.objects.create_user(
                username="jacob", email="jacob@…", password="top_secret"
            )

        def test_details(self):
            # Create an instance of a GET request.
            request = self.factory.get("/customer/details")

            # Recall that middleware are not supported. You can simulate a
            # logged-in user by setting request.user manually.
            request.user = self.user

            # Or you can simulate an anonymous user by setting request.user to
            # an AnonymousUser instance.
            request.user = AnonymousUser()

            # Test my_view() as if it were deployed at /customer/details
            response = my_view(request)
            # Use this syntax for class-based views.
            response = MyView.as_view()(request)
            self.assertEqual(response.status_code, 200)

### AsyncRequestFactory

class AsyncRequestFactory

`RequestFactory` crée des requêtes de type WSGI. Si vous souhaitez créer des requêtes de type ASGI, ayant aussi une portée `scope` ASGI correcte, vous pouvez utiliser `django.test.AsyncRequestFactory` à la place.

L’API de cette classe est directement compatible avec `RequestFactory`, avec comme seule différence le renvoi d’instances `ASGIRequest` au lieu de `WSGIRequest`. Toutes ses méthodes restent des exécutables synchrones.

Les paramètres mot-clé arbitraires dans `defaults` sont ajoutés directement dans la portée ASGI.

## Test des vues fondées sur les classes

Afin de tester les vues fondées sur des classes en dehors du cycle requête/réponse, vous devez vous assurer qu’elles sont configurées correctement en appelant `setup()` après leur instanciation.

Par exemple, en partant de la vue classe suivante :

`views.py`

    from django.views.generic import TemplateView

    class HomeView(TemplateView):
        template_name = "myapp/home.html"

        def get_context_data(self, **kwargs):
            kwargs["environment"] = "Production"
            return super().get_context_data(**kwargs)

Vous pouvez directement tester la méthode `get_context_data()` en commençant par créer une instance de la vue, puis en passant une requête à `setup()` avant de procéder au test du code :

`tests.py`

    from django.test import RequestFactory, TestCase
    from .views import HomeView

    class HomePageTest(TestCase):
        def test_environment_set_in_context(self):
            request = RequestFactory().get("/")
            view = HomeView()
            view.setup(request)

            context = view.get_context_data()
            self.assertIn("environment", context)

## Tests avec plusieurs noms d’hôtes

Le réglage `ALLOWED_HOSTS` est validé lors de l’exécution des tests. Cela permet au client de test de faire la différence entre les URL internes et externes.

Les projets qui gèrent plusieurs domaines par site ou adaptent leur comportement en fonction de l’hôte de la requête et qui utilisent des noms d’hôte particuliers dans les tests doivent inclure ces noms d’hôte dans `ALLOWED_HOSTS`.

La première option pour accomplir cela est d’ajouter les hôtes dans le fichier des réglages. Par exemple, la suite de tests de docs.djangoproject.com contient ceci :

    from django.test import TestCase

    class SearchFormTestCase(TestCase):
        def test_empty_get(self):
            response = self.client.get(
                "/en/dev/search/",
                headers={"host": "docs.djangoproject.dev:8000"},
            )
            self.assertEqual(response.status_code, 200)

et le fichier des réglages contient une liste des domaines pris en charge par le projet :

    ALLOWED_HOSTS = ["www.djangoproject.dev", "docs.djangoproject.dev", ...]

Une autre option est d’ajouter les hôtes nécessaires dans `ALLOWED_HOSTS` en utilisant `override_settings()` ou `modify_settings`. Cette option peut être préférable pour les applications autonomes qui ne peuvent pas fournir leur propre fichier de réglages ou pour les projets dont la liste des domaines n’est pas figée (par ex. des sous-domaines dans un service partagé). Par exemple, il serait possible d’écrire un test pour le domaine `http://otherserver/` comme ceci :

    from django.test import TestCase, override_settings

    class MultiDomainTestCase(TestCase):
        @override_settings(ALLOWED_HOSTS=["otherserver"])
        def test_other_domain(self):
            response = self.client.get("http://otherserver/foo/bar/")

La désactivation du contrôle de `ALLOWED_HOSTS` (`ALLOWED_HOSTS = ['*']`) lors de l’exécution des tests empêche le client de test de produire un message d’erreur instructif si une redirection est appelée pour une URL externe.

## Tests avec plusieurs base de données

### Test des configurations primaire/réplique

Si vous testez une configuration avec plusieurs bases de données impliquant une réplication primaire/réplique (désignée comme maître/esclave par certaines bases de données), cette stratégie de création de bases de données de test pose un problème. Lorsque les bases de données de test sont créées, la réplication n’a pas lieu et par conséquent, les données créées sur la base primaire ne seront pas visibles sur les répliques.

Pour contourner ce problème, Django permet de définir une base de données comme un miroir de test. Considérez cet exemple (simplifié) de configuration de bases de données :

    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.mysql",
            "NAME": "myproject",
            "HOST": "dbprimary",
            # ... plus some other settings
        },
        "replica": {
            "ENGINE": "django.db.backends.mysql",
            "NAME": "myproject",
            "HOST": "dbreplica",
            "TEST": {
                "MIRROR": "default",
            },
            # ... plus some other settings
        },
    }

Dans cette configuration figurent deux serveurs de base de données : `dbprimary`, défini par l’alias de base de données `default` et `dbreplica`, défini par l’alias `replica`. Comme l’on peut s’y attendre, `dbreplica` a été configuré par l’administrateur de base de données comme réplique en lecture de `dbprimary`. En temps normal, toute écriture sur `default` apparaît aussi sur `replica`.

Si Django avait créé deux bases de données de test indépendantes, cela casserait d’éventuels tests s’attendant à de la réplication. Cependant, la base de données `replica` a été configurée comme miroir de test (via le réglage de test `MIRROR`), indiquant par là que lors des tests, `replica` doit être traité comme un miroir de `default`.

Au moment de la création de l’environnement de test, aucune base ne sera créée pour `replica`. Par contre, la connexion vers `replica` sera redirigée pour pointer vers `default`. Par conséquent, les écritures sur `default` apparaîtront aussi sur `replica`, mais parce qu’il s’agit en réalité de la même base de données, car aucune réplication de données ne sera mise en place entre les deux bases de données. Comme cela dépend des transactions, les tests doivent utiliser `TransactionTestCase` au lieu de `TestCase`.

### Ordre de création des bases de données de test

Par défaut, Django part du principe que toutes les bases de données dépendent de la base de données `default` et va par conséquent toujours créer celle-ci en premier. Cependant, pour toute autre base de données de votre configuration de test, il n’y a aucune garantie sur l’ordre de création des bases de données.

Si votre configuration de base de données nécessite un ordre de création bien défini, vous pouvez indiquer les dépendances entre bases de données dans le réglage de test `DEPENDENCIES`. Considérez cet exemple (simplifié) de configuration de bases de données :

    DATABASES = {
        "default": {
            # ... db settings
            "TEST": {
                "DEPENDENCIES": ["diamonds"],
            },
        },
        "diamonds": {
            # ... db settings
            "TEST": {
                "DEPENDENCIES": [],
            },
        },
        "clubs": {
            # ... db settings
            "TEST": {
                "DEPENDENCIES": ["diamonds"],
            },
        },
        "spades": {
            # ... db settings
            "TEST": {
                "DEPENDENCIES": ["diamonds", "hearts"],
            },
        },
        "hearts": {
            # ... db settings
            "TEST": {
                "DEPENDENCIES": ["diamonds", "clubs"],
            },
        },
    }

Avec cette configuration, la base de données `diamonds` sera créée en premier car c’est le seul alias de base de données sans dépendances. Les alias `default` et `clubs` seront ensuite créés (bien que l’ordre de création de ceux-ci ne soit pas défini), puis `hearts` et enfin, `spades`.

Si la définition de `DEPENDENCIES` comporte des dépendances circulaires, une exception `ImproperlyConfigured` sera générée.

## Fonctionnalités avancées de `TransactionTestCase`

TransactionTestCase.available_apps

  Avertissement

  Cet attribut est une API privée. Il peut être modifié ou supprimé dans une version future sans période d’obsolescence, par exemple pour s’adapter à des modifications du processus de chargement des applications.

  Il est utilisé pour optimiser la suite de tests de Django lui-même qui contient des centaines de modèles mais sans relations entre les modèles des différentes applications de test.

  Par défaut, `available_apps` vaut `None`. Après chaque test, Django appelle `flush` pour réinitialiser l’état de la base de données. Toutes les tables sont ainsi vidées et le signal `post_migrate` est émis, ce qui recrée un type de contenu et quatre permissions pour chaque modèle. Cette opération s’alourdit proportionnellement au nombre de modèles.

  En définissant `available_apps` à une liste d’applications, Django se comporte comme si seuls les modèles de ces applications étaient disponibles. Le comportement de `TransactionTestCase` est modifié comme suit :

  - `post_migrate` est émis avant chaque test pour créer les types de contenu et les permissions de chaque modèle des applications disponibles, dans le cas où ils manqueraient.

  - Après chaque test, Django ne vide que les tables correspondants aux modèles des applications disponibles. Cependant, au niveau de la base de données, il est possible que les troncatures s’appliquent en cascade à des modèles liés dans des applications non disponibles. De plus, `post_migrate` n’est pas émis ; il sera émis par le prochain test `TransactionTestCase`, après que l’ensemble d’applications adéquat a été sélectionné.

  Comme la base de données n’est pas complètement vidée, si un test crée des instances de modèles non inclus dans `available_apps`, ces instances vont rester et pourraient être la cause d’échecs de tests non liés. Restez prudent avec les tests employant des sessions ; le moteur de sessions par défaut les stocke dans la base de données.

  Comme `post_migrate` n’est pas émis après la réinitialisation de la base de données, son état après un `TransactionTestCase` n’est pas le même qu’après un `TestCase`: les lignes créées par les récepteurs de `post_migrate` sont manquantes. Mais sachant l’ordre dans lequel les tests sont exécutés, ce n’est pas un problème, dans la mesure où soit tous les tests `TransactionTestCase` d’une suite de tests déclarent `available_apps`, soit aucun.

  `available_apps` est obligatoire dans la propre suite de tests de Django.

TransactionTestCase.reset_sequences

  En définissant `reset_sequences = True` d’une classe `TransactionTestCase`, vous vous assurez que les séquences sont toujours réinitialisées avant le lancement du test :

      class TestsThatDependsOnPrimaryKeySequences(TransactionTestCase):
          reset_sequences = True

          def test_animal_pk(self):
              lion = Animal.objects.create(name="lion", sound="roar")
              # lion.pk is guaranteed to always be 1
              self.assertEqual(lion.pk, 1)

  À l’exception des cas où vous testez explicitement les numéros de séquence de clés primaires, il est recommandé de ne pas tester des valeurs de clés primaires figées.

  L’utilisation de `reset_sequences = True` ralentit les tests, car la réinitialisation des clés primaires est une opération de base de données relativement coûteuse.

## Exécution séquentielle forcée des classes de tests

Si vous avez des classes de tests qui ne peuvent pas fonctionner en parallèle (par exemple si elles partagent une ressource commune), vous pouvez utiliser `django.test.testcases.SerializeMixin` pour les exécuter de manière séquentielle. Cette classe mixin utilise un fichier verrou `lockfile` du système de fichiers.

Par exemple, vous pouvez utiliser `__file__` pour déterminer que toutes les classes de tests du même fichier héritant de `SerializeMixin` seront exécutées les unes à la suite des autres

    import os

    from django.test import TestCase
    from django.test.testcases import SerializeMixin

    class ImageTestCaseMixin(SerializeMixin):
        lockfile = __file__

        def setUp(self):
            self.filename = os.path.join(temp_storage_dir, "my_file.png")
            self.file = create_file(self.filename)

    class RemoveImageTests(ImageTestCaseMixin, TestCase):
        def test_remove_image(self):
            os.remove(self.filename)
            self.assertFalse(os.path.exists(self.filename))

    class ResizeImageTests(ImageTestCaseMixin, TestCase):
        def test_resize_image(self):
            resize_image(self.file, (48, 48))
            self.assertEqual(get_image_size(self.file), (48, 48))

## Utilisation du lanceur de tests de Django pour tester des applications réutilisables

Si vous écrivez une application réutilisable, il peut être intéressant d’utiliser le lanceur de tests de Django pour lancer votre propre suite de tests et bénéficier ainsi de l’infrastructure de tests de Django.

Une pratique courante est de placer un répertoire tests en parallèle de votre code d’application, avec la structure suivante :

    runtests.py
    polls/
        __init__.py
        models.py
        ...
    tests/
        __init__.py
        models.py
        test_settings.py
        tests.py

Examinons ce qui se trouve dans certains de ces fichiers :

`runtests.py`

    #!/usr/bin/env python
    import os
    import sys

    import django
    from django.conf import settings
    from django.test.utils import get_runner

    if __name__ == "__main__":
        os.environ["DJANGO_SETTINGS_MODULE"] = "tests.test_settings"
        django.setup()
        TestRunner = get_runner(settings)
        test_runner = TestRunner()
        failures = test_runner.run_tests(["tests"])
        sys.exit(bool(failures))

Il s’agit ici du script invoqué pour lancer la suite de tests. Il met en place l’environnement Django, crée la base de données de tests et lance les tests.

Par souci de clarté, cet exemple ne contient que le strict minimum nécessaire à l’utilisation du lanceur de tests de Django. On peut cependant imaginer ajouter des options en ligne de commande pour le contrôle de la verbosité, pour passer des étiquettes de tests spécifiques à lancer, etc.

`tests/test_settings.py`

    SECRET_KEY = "fake-key"
    INSTALLED_APPS = [
        "tests",
    ]

Ce fichier contient les réglages Django indispensables pour lancer les tests de votre application.

Encore une fois, il s’agit d’un exemple minimal ; les tests peuvent exiger des réglages supplémentaires pour fonctionner.

Comme le paquet tests est inclus dans `INSTALLED_APPS` au moment de lancer les tests, il est possible de définir des modèles uniquement pour les tests dans le fichier `models.py`.

## Utilisation d’autres infrastructures de test

Il est clair que `unittest` n’est pas la seule infrastructure de test de Python. Même si Django ne fournit pas de prise en charge explicite d’autres systèmes de test, il offre une manière d’invoquer des tests construits pour un autre système comme s’il s’agissait de tests Django normaux.

Lorsque vous lancez `./manage.py test`, Django consulte le réglage `TEST_RUNNER` pour déterminer ce qu’il doit faire. Par défaut, `TEST_RUNNER` contient `'django.test.runner.DiscoverRunner'`. Cette classe définit le comportement de test par défaut de Django. Ce comportement implique :

1. Une préparation générale avant les tests.

2. La recherche de tests dans tout fichier au-dessous du répertoire actuel dont le nom correspond au motif `test*.py`.

3. La création des bases de données de test.

4. Le lancement de `migrate` pour installer les modèles et les données initiales dans les bases de données de test.

5. L’exécution des vérifications systèmes.

6. L’exécution des tests découverts.

7. La suppression des bases de données de test.

8. Une finalisation générale après les tests.

Si vous définissez votre propre classe de lanceur de tests et que vous indiquez cette classe dans `TEST_RUNNER`, Django se servira de votre lanceur de tests lors de chaque appel à `./manage.py test`. De cette façon, il est possible d’utiliser n’importe quel système de test pouvant être lancé à partir de code Python ou de modifier le processus d’exécution des tests Django pour adapter les tests à d’éventuels besoins spécifiques.

### Définition d’un lanceur de tests

Un lanceur de tests est une classe définissant une méthode `run_tests()`. Django fournit une classe `DiscoverRunner` définissant le comportement de test par défaut de Django. Cette classe définit le point d’entrée `run_tests()` ainsi qu’une sélection d’autres méthodes utilisées par `run_tests()` pour préparer, exécuter et clore la suite de tests.

class DiscoverRunner(pattern='test*.py', top_level=None, verbosity=1, interactive=True, failfast=False, keepdb=False, reverse=False, debug_mode=False, debug_sql=False, parallel=0, tags=None, exclude_tags=None, test_name_patterns=None, pdb=False, buffer=False, enable_faulthandler=True, timing=True, shuffle=False, logger=None, durations=None, **kwargs)

  `DiscoverRunner` recherche des tests dans tout fichier correspondant au motif `pattern`.

  `top_level` peut être utilisé pour indiquer le répertoire contenant les modules Python de premier niveau. Django peut généralement le découvrir automatiquement, ce qui fait que cette option n’est pas absolument nécessaire. Lorsqu’elle est définie, elle devrait en principe correspondre au répertoire contenant le fichier `manage.py`.

  `verbosity` détermine la quantité de notifications et d’informations de débogage qui s’afficheront sur la console ; `0` n’affiche rien, `1` correspond à l’affichage normal et `2` à l’affichage verbeux.

  Si `interactive` vaut `True`, la suite de tests a le droit de poser des questions à l’utilisateur durant son exécution. Par exemple, elle pourrait demander la permission de supprimer une base de données de test existante. Si `interactive` vaut `False`, la suite de tests doit pouvoir s’exécuter sans aucune intervention manuelle de l’utilisateur.

  Si `failfast` vaut `True`, la suite de tests s’arrête immédiatement après le premier échec de test.

  Si `keepdb` vaut `True`, la suite de tests va utiliser la base de données existante ou en créer une si c’est nécessaire. Si la valeur est `False`, une nouvelle base de données est toujours créée, demandant à l’utilisateur de supprimer une éventuelle base existante de même nom.

  Si `reverse` vaut `True`, les cas de tests sont exécutés dans l’ordre inverse. Cela peut être utile pour déboguer des tests qui ne sont pas isolés correctement et génèrent des effets de bord. Le groupement par classe de test est conservé lors de l’utilisation de cette option. Celle-ci peut être utilisée conjointement avec `--shuffle` pour inverser l’ordre d’une graine aléatoire particulière.

  `debug_mode` indique la valeur que doit prendre le réglage `DEBUG` avant d’exécuter les tests.

  `parallel` indique le nombre de processus. Si `parallel` est plus grand que `1`, la suite de tests s’exécutera dans des processus en parallèle. S’il y a moins de classes de cas de test que de processus configurés, Django se charge de réduire le nombre de processus en conséquence. Chaque processus reçoit sa propre base de données. Cette option nécessite la présence du paquet tiers `tblib` pour afficher correctement les traces d’erreurs.

  `tags` peut être utilisé pour définir un jeu d’étiquettes pour le filtrage des tests. Peut être combiné avec `exclude_tags`.

  `exclude_tags` peut être utilisé pour définir un jeu d’étiquettes pour l’exclusion de tests. Peut être combiné avec `tags`.

  Si `debug_sql` vaut `True`, les tests en échec affichent les requêtes SQL journalisées vers django.db.backends en plus de la pile d’appels. Si `verbosity` vaut `2`, les requêtes de tous les tests sont affichées.

  `test_name_patterns` peut être utilisé pour définir un ensemble de motifs pour filtrer les méthodes et classes de test par leur nom.

  Si `pdb` vaut `True`, un débogueur (`pdb` ou `ipdb`) sera déclenché lors de chaque erreur ou échec de test.

  Si `buffer` vaut `True`, la sortie des tests réussis sera omise.

  Si `enable_faulthandler` vaut `True`, `faulthandler` sera activé.

  Si `timing` vaut `True`, la mesure temporelle des tests sera affichée, y compris la mise en place de la base de données et le temps total d’exécution.

  Si `shuffle` est un nombre entier, les cas de test seront mélangés aléatoirement avant leur exécution, en utilisant le nombre entier comme facteur aléatoire. Si `shuffle` vaut `None`, ce facteur sera généré aléatoirement. Dans les deux cas, le facteur sera journalisé et défini dans `self.shuffle_seed` avant de lancer les tests. Cette option peut être utilisée pour aider à détecter les tests qui ne sont pas proprement isolés. Le groupement par classe de test est conservé avec cette option.

  `logger` peut être utilisé pour passer un objet Logger Python. Si indiqué, ce journaliseur sera utilisé pour journaliser les messages au lieu de les afficher dans la console. Cet objet journaliseur respectera son niveau de journalisation plutôt que le paramètre `verbosity`.

  `durations` affiche une liste des N cas de tests les plus lents. En définissant cette option à `0`, la durée de tous les tests sera affichée.

  Il est possible que de temps à autre, Django étende les capacités du lanceur de tests en ajoutant de nouveaux paramètres. La déclaration `**kwargs` permet cette extension. Si vous héritez de `DiscoverRunner` ou que vous écrivez votre propre lanceur de tests, vérifiez qu’il accepte `**kwargs`.

  Votre lanceur de tests peut aussi définir des options supplémentaires en ligne de commande. Créez ou surchargez une méthode de classe `add_arguments(cls, parser)` et ajoutez des paramètres personnalisés en appelant `parser.add_argument()` dans cette méthode, afin que la commande `test` puisse exploiter ces paramètres.

#### Attributs

DiscoverRunner.test_suite

  La classe utilisée pour construire la suite de tests. Par défaut, il s’agit de `unittest.TestSuite`. Il est possible de surcharger cette valeur si vous souhaitez implémenter une logique différente pour collecter les tests.

DiscoverRunner.test_runner

  Cette classe est celle du lanceur de tests de bas niveau utilisé pour exécuter les tests individuels et mettre en forme les résultats. Par défaut, il s’agit de `unittest.TextTestRunner`. Malgré la malencontreuse similitude des conventions de nommage, il ne s’agit pas du même type de classe que `DiscoverRunner`, qui prend en charge un plus grand spectre de responsabilités. Vous pouvez surcharger cet attribut pour modifier la façon dont les tests sont exécutés et leurs résultats affichés.

DiscoverRunner.test_loader

  Il s’agit de la classe qui charge les tests, que ce soit à partir de classes `TestCase`, de modules ou d’autres façons, et qui les consolide en suites de tests que le lanceur pourra exécuter. Par défaut, c’est `unittest.defaultTestLoader`. Vous pouvez surcharger cet attribut si vos tests doivent être chargés de manière inhabituelle.

#### Méthodes

DiscoverRunner.run_tests(test_labels, **kwargs)

  Lance la suite de tests.

  `test_labels` permet d’indiquer les tests à exécuter et accepte plusieurs formats (voir `DiscoverRunner.build_suite()` pour la liste des formats pris en charge).

  Cette méthode doit renvoyer le nombre de tests ayant échoué.

classmethod DiscoverRunner.add_arguments(parser)

  Surchargez cette méthode de classe pour ajouter des paramètres personnalisés acceptés par la commande d’administration `test`. Voir `argparse.ArgumentParser.add_argument()` pour plus de détails au sujet de l’ajout de paramètres de ligne de commande.

DiscoverRunner.setup_test_environment(**kwargs)

  Met en place l’environnement de test en appelant `setup_test_environment()` et en définissant `DEBUG` à `self.debug_mode` (`False` par défaut).

DiscoverRunner.build_suite(test_labels=None, **kwargs)

  Construit une suite de tests correspondant aux noms de test indiqués.

  `test_labels` est une liste de chaînes décrivant les tests à exécuter. Un nom de test peut apparaître sous quatre formes :

  - `chemin.vers.module_test.TestCase.methode_test` – Lance une seule méthode de test dans une classe de cas de test.

  - `chemin.vers.module_test.TestCase` – Lance toutes les méthodes de test d’un cas de test.

  - `chemin.vers.module` – Recherche et lance tous les tests d’un paquet ou module Python donné.

  - `chemin/vers/répertoire` – Recherche et lance tous les tests dans la sous-arborescence du répertoire donné.

  Si `test_labels` contient la valeur `None`, le lanceur de tests recherche des tests dans tous les fichiers au-dessous du répertoire actuel dont le nom correspond à son motif `pattern` (voir ci-dessus).

  Renvoie une instance `TestSuite` prête à être exécutée.

DiscoverRunner.setup_databases(**kwargs)

  Crée les bases de données de test en appelant `setup_databases()`.

DiscoverRunner.run_checks(databases)

  Lance les vérifications systèmes pour les bases `databases` de test.

DiscoverRunner.run_suite(suite, **kwargs)

  Lance la suite de tests.

  Renvoie le résultat produit par l’exécution de la suite de tests.

DiscoverRunner.get_test_runner_kwargs()

  Renvoie les paramètres nommés pour l’instanciation de `DiscoverRunner.test_runner`.

DiscoverRunner.teardown_databases(old_config, **kwargs)

  Supprime les bases de données de test, rétablissant la situation d’avant-test en appelant `teardown_databases()`.

DiscoverRunner.teardown_test_environment(**kwargs)

  Rétablit l’environnement à son état d’avant les tests.

DiscoverRunner.suite_result(suite, result, **kwargs)

  Calcule et renvoie un code de retour basé sur une suite de tests et des résultats de ces tests.

DiscoverRunner.log(msg, level=None)

  Quand le paramètre `logger` est défini, journalise le message au niveau de journalisation donné (nombre entier), par ex. `logging.DEBUG`, `logging.INFO` ou `logging.WARNING`. Sinon, le message est affiché dans la console en respectant le paramètre `verbosity` en cours. Par exemple, aucun message ne sera affiché si `verbosity` vaut 0, les niveaux `INFO` et supérieurs seront affichés si `verbosity` vaut au moins 1, et les niveaux `DEBUG` seront affichés si `verbosity` vaut au moins 2. La valeur par défaut de `level` est `logging.INFO`.

### Utilitaires de test

#### `django.test.utils`

Pour aider à la création de votre propre lanceur de tests, Django fournit un certain nombre de méthodes utilitaires dans le module `django.test.utils`.

setup_test_environment(debug=None)

  Effectue la mise en place générale avant les tests, comme l’installation des adaptations du système de rendu des gabarits et la mise en place de la boîte de messagerie factice.

  Si `debug` ne vaut pas `None`, le réglage `DEBUG` est mis à jour avec cette valeur.

teardown_test_environment()

  Effectue la finalisation générale après les tests, comme la suppression des adaptations du système des gabarits et le rétablissement des services de messagerie par défaut.

setup_databases(verbosity, interactive, *, time_keeper=None, keepdb=False, debug_sql=False, parallel=0, aliases=None, serialized_aliases=None, **kwargs)

  Crée les bases de données de test.

  Renvoie une structure de données fournissant suffisamment de détails pour annuler les changements effectués. Ces données sont ensuite transmises à la fonction `teardown_databases()` lors de la finalisation des tests.

  Le paramètre `aliases` détermine pour quels alias de `DATABASES` les bases de données de test doivent être préparées. S’il n’est pas présent, sa valeur par défaut contient tous les alias de `DATABASES`.

  Le paramètre `serialized_aliases` détermine le sous-ensemble des `aliases` de bases de données de test qui devraient avoir leur état sérialisé pour permettre l’utilisation de la fonctionnalité serialized_rollback. Si non défini, la valeur par défaut est `aliases`.

teardown_databases(old_config, parallel=0, keepdb=False)

  Supprime les bases de données de test, rétablissant la situation d’avant-test.

  `old_config` est une structure de données définissant les modifications de la configuration des bases de données qui doivent être annulées. C’est la valeur de renvoi de la méthode `setup_databases()`.

#### `django.db.connection.creation`

Le module de création du moteur de base de données propose également quelques utilitaires pouvant être utiles durant les tests.

create_test_db(verbosity=1, autoclobber=False, keepdb=False)

  Crée une nouvelle base de données de test et exécute `migrate` sur cette base.

  `verbosity` a le même effet que dans `run_tests()`.

  `autoclobber` décrit le comportement adopté si une base de données de même nom que la base de données de test existe déjà :

  - Si `autoclobber` vaut `False`, l’utilisateur devra confirmer la suppression de la base de données existante. `sys.exit` est appelée si l’utilisateur refuse.

  - Si `autoclobber` vaut `True`, la base de données est supprimée sans rien demander à l’utilisateur.

  `keepdb` détermine si la session de test doit utiliser une base de données existante ou si elle doit en créer une nouvelle. Si `True`, une éventuelle base de données existante est utilisée, sinon une nouvelle base est créée. Si `False`, une nouvelle base de données sera créée dans tous les cas, en demandant à l’utilisateur s’il doit supprimer la base existante, s’il y en a une.

  Renvoie le nom de la base de données de test qui a été créée.

  `create_test_db()` présente un effet de bord : la valeur de `NAME` dans `DATABASES` est mise à jour pour correspondre au nom de la base de données de test.

  Obsolète depuis la version 6.0: L’argument nommé `serialize` est obsolète. La transmission de `serialize=True` appelait automatiquement `serialize_db_to_string()`, mais cela a été rendu obsolète, car cela pouvait amener à exécuter des requêtes sur des bases de données de production au lieu de test lors de la sérialisation.

destroy_test_db(old_database_name, verbosity=1, keepdb=False)

  Supprime la base de données dont le nom correspond à la valeur de `NAME` dans `DATABASES` et met à jour `NAME` avec la valeur contenue dans `old_database_name`.

  Le paramètre `verbosity` a le même effet que pour `DiscoverRunner`.

  Si le paramètre `keepdb` vaut `True`, la connexion à la base de données sera fermée, mais la base de données ne sera pas détruite.

serialize_db_to_string()

  Sérialise la base de données en une chaîne JSON en mémoire pouvant être utilisée pour restaurer l’état de la base de données entre les tests si le moteur ne gère par les transactions ou si votre suite de tests contient des tests avec la propriété serialized_rollback=True.

  Cette fonction ne devrait être appelée qu’après la création de toutes les bases de données de test car le processus de sérialisation pourrait aboutir à des requêtes appliquées sur des bases de données « non test », en fonction de votre configuration de routage.

## Intégration avec `coverage.py`

La couverture de code représente la quantité de code source mis à l’épreuve par les tests. Elle montre quelles sont les parties de code que les tests éprouvent et les parties qui ne le sont pas. C’est un aspect important du test des applications, c’est pourquoi il est fortement recommandé de contrôler la couverture de vos tests.

Django peut facilement s’intégrer à coverage.py, un outil de mesure de couverture du code de programmes Python. Premièrement, installez coverage. Puis, lancez la commande suivante à partir du répertoire de votre projet contenant `manage.py`:

    coverage run --source='.' manage.py test myapp

Cela va lancer les tests et collecter les données de couverture des fichiers exécutés dans votre projet. Vous pouvez afficher un rapport de ces données en saisissant la commande suivante :

    coverage report

Notez que du code Django a été exécuté lors de l’exécution des tests, mais il ne figure pas dans le rapport à cause de l’option `source` indiquée dans la commande précédente.

Pour davantage d’options comme les listings HTML annotés détaillant les lignes manquantes, consultez la documentation de coverage.py.