L'application mayan/apps/testing/ fournit l'infrastructure commune de tests de Mayan EDMS. Elle étend le runner Django standard, expose des classes de base riches en mixins, et fournit des utilitaires (adaptateur HTTP, mocks, checks de cohérence).
MayanTestRunnerRemplace le DiscoverRunner Django. Il ajoute trois arguments CLI supplémentaires :
| Argument | Description |
|---|---|
--mayan-apps |
Teste automatiquement toutes les apps Mayan déclarant has_tests = True |
--skip-migrations |
Remplace MIGRATION_MODULES par NullMigrationsClass → crée les tables directement depuis les modèles, sans exécuter les migrations (plus rapide) |
--no-exclude |
Inclut les tests marqués @tag('exclude') (exclus par défaut) |
NullMigrationsClassclass NullMigrationsClass:
def __contains__(self, item): return True
def __getitem__(self, item): return None
Toute lookup dans MIGRATION_MODULES retourne None, ce qui indique à Django de créer les tables directement depuis les modèles sans passer par les fichiers de migration.
excludeLe tag 'exclude' (défini dans literals.py) est automatiquement ajouté à exclude_tags sauf si --no-exclude est passé. Utilisé pour marquer les tests longs ou spéciaux (ex. : MayanMigratorTestCase).
Après la suite, shutil.rmtree(settings.MEDIA_ROOT_TEMPORARY) supprime le dossier media temporaire créé pendant les tests.
Django TestCase / TransactionTestCase
└── BaseTestCaseMixin (assemblage de tous les mixins)
├── BaseTestCase ← test case standard
│ ├── GenericViewTestCase ← + ClientMethodsTestCaseMixin + vues de test
│ └── MayanMigratorTestCase ← tests de migrations (tagué 'exclude')
└── BaseTransactionTestCase ← pour les tests nécessitant de vraies transactions
└── GenericTransactionViewTestCase
BaseTestCaseMixinAgrège tous les mixins de test du projet. Chaque mixin est responsable d'un aspect :
| Mixin | Rôle |
|---|---|
DelayTestCaseMixin |
_test_delay(seconds) — pause contrôlée dans les tests |
TestCaseMixinSilenceLogger |
Supprime les logs pendant les tests |
ConnectionsCheckTestCaseMixin |
Vérifie qu'aucune connexion DB n'est laissée ouvertes |
RandomPrimaryKeyModelMonkeyPatchMixin |
Randomise les PK pour détecter les dépendances d'ordre |
EventTestCaseMixin |
Capture et assert les événements Mayan émis |
LayerTestCaseMixin |
Gestion des layers de conversion (converter) |
ACLTestCaseMixin |
Helpers pour créer des ACL dans les tests |
ModelTestCaseMixin |
Helpers pour créer des modèles de test |
OpenFileCheckTestCaseMixin |
Détecte les fichiers ouverts non fermés après le test |
DescriptorLeakCheckTestCaseMixin |
Détecte les fuites de descripteurs de fichiers (moins précis qu'OpenFile) |
PermissionTestCaseMixin |
Helpers pour créer des permissions et des rôles |
SettingTestMixin |
Override temporaire de settings Mayan pendant un test |
TempfileCheckTestCasekMixin |
Vérifie qu'aucun fichier temporaire n'est laissé après le test |
UserTestMixin |
Crée des utilisateurs de test (admin, utilisateur normal) |
TestModelTestCaseMixin |
Helpers pour créer des modèles Django temporaires pour les tests |
Par défaut, _skip_file_descriptor_test et _skip_open_file_leak_test sont True dans BaseTestCaseMixin — les checks de fuite sont optionnels et peuvent être activés par test.
GenericViewTestCaseClasse de référence pour tester les vues Django de Mayan. Ajoute à BaseTestCase :
ClientMethodsTestCaseMixin — méthodes get(), post(), generic() préconfigurées avec gestion de l'authentificationContentTypeCheckTestCaseMixin — vérifie automatiquement le Content-Type de chaque réponse HTTPTestViewTestCaseMixin — enregistre une vue de test temporaire dans les URLsclass MyViewTest(GenericViewTestCase):
def test_document_list(self):
self._create_test_document_type()
response = self.get(viewname='documents:document_list')
self.assertEqual(response.status_code, 200)
MayanMigratorTestCaseHérite de MigratorTestCase (django-test-migrations). Permet de tester des migrations individuelles. Tagué @tag('exclude') → non exécuté par défaut.
Nettoie le cache des ContentType Django dans tearDown() pour éviter les faux positifs entre tests de migration.
ContentTypeCheckTestCaseMixinMonkey-patche le client Django de test avec MayanCustomClient qui vérifie automatiquement que chaque réponse HTTP a un Content-Type dans expected_content_types (défaut : text/html / text/html; charset=utf-8).
Pour les vues retournant du JSON ou autre, surcharger l'attribut :
class MyAPITest(GenericViewTestCase):
expected_content_types = ('application/json',)
EnvironmentTestCaseMixinPermet de définir des variables d'environnement temporaires, nettoyées automatiquement dans tearDown() :
self._set_environment_variable('MAYAN_DATABASES', '...')
TestMixinObjectCreationTrackSuivi de création d'objets DB entre deux points dans le temps. Utile pour vérifier qu'exactement un objet a été créé pendant une opération :
self._test_object_pk_list = list(MyModel.objects.values_list('pk', flat=True))
# ... action qui crée un objet ...
self._test_object_set() # self._test_object → le nouvel objet
self._test_object_list_set() # self._test_object_list → queryset des nouveaux objets
DelayTestCaseMixinself._test_delay(seconds=0.1) # pause dans un test (ex. : attendre un signal async)
@skip_file_descriptor_check# mayan/apps/testing/tests/decorators.py
@skip_file_descriptor_check
def test_my_case(self):
...
Désactive le check de descripteur de fichier ouvert pour un test spécifique (utile quand le test ouvre intentionnellement un fichier sans le fermer).
TestClientAdapter — adaptateur HTTP pour les testsPermet de tester du code qui fait des appels HTTP avec la librairie requests, en redirigeant les appels vers le client de test Django :
# mayan/apps/testing/tests/http_adapters.py
class TestClientAdapter(requests.adapters.BaseAdapter):
def send(self, request, ...):
django_response = self.test_case.generic(
method=request.method,
viewname=self.test_case._test_view_name,
data=request.body,
headers=request.headers
)
return self.build_response(request, django_response)
Utilisé via request_method_factory :
# Dans un test de WorkflowAction HTTP :
import requests
session = requests.Session()
session.get_adapter = request_method_factory(test_case=self, content=b'ok')
Cela permet de tester les actions HTTP sans faire de vraies requêtes réseau.
check_app_testsEnregistré au démarrage via checks.register. Vérifie la cohérence de l'attribut has_tests sur chaque app Mayan :
| Situation | Warning |
|---|---|
has_tests = True mais aucun test trouvé |
mayan_apps.W001 |
has_tests = False (ou absent) mais des tests existent |
mayan_apps.W002 |
Exécuter avec : ./manage.py check --settings=mayan.settings.development
make# Tests d'une app spécifique (skip-migrations par défaut)
make test MODULE=mayan.apps.documents
# Toutes les apps avec has_tests=True
make test-all
# Tests avec PostgreSQL
make test-with-postgresql MODULE=mayan.apps.documents
# Tests de migration (--no-exclude pour inclure MayanMigratorTestCase)
make test-migrations MODULE=mayan.apps.documents
# Directement via manage.py
./manage.py test mayan.apps.documents \
--settings=mayan.settings.testing.development \
--skip-migrations