Une application réutilisable pour tester les vues django
Project description
🚀 Django AutoTest
Arrêtez de perdre du temps à écrire des tests répétitifs. Configurez, et c'est parti !
Django AutoTest est un framework de test automatisé qui génère vos tests Django à partir d'une simple configuration. Fini le copier-coller de code boilerplate pour tester chaque vue — définissez votre config, et laissez le framework faire le reste.
# Au lieu d'écrire ça pour CHAQUE vue...
class ProductListViewTest(TestCase):
def setUp(self):
self.product1 = Product.objects.create(name="Test", price=10)
self.product2 = Product.objects.create(name="Test2", price=20)
def test_get_request(self):
response = self.client.get(reverse('product-list'))
self.assertEqual(response.status_code, 200)
self.assertIn('products', response.context)
def test_post_not_allowed(self):
response = self.client.post(reverse('product-list'))
self.assertEqual(response.status_code, 405)
# ... 50 lignes de plus ...
# Vous écrivez juste ça :
class ProductListViewTest(AutoTestCase):
config = AutoTestCaseConfig(
config={
"view": ProductListView,
"url_name": "product-list",
"fixtures": [{"model": Product, "count": 5}],
"method_allowed": {"GET": {"enabled": True}}
}
)
Résultat : Tous les tests sont générés automatiquement. Status codes, contexte, champs requis, validation, formulaires — tout est testé sans écrire une ligne de code de test.
📋 Table des matières
- Pourquoi Django AutoTest ?
- Fonctionnalités
- Installation
- Utilisation rapide
- Exemples détaillés
- Architecture
- Configuration complète
- Multilingue (FR/EN)
- Contribuer
- Issues & Roadmap
- Licence
🎯 Pourquoi Django AutoTest ?
Le problème
Quand vous développez une application Django avec 20, 50 ou 100 vues, écrire des tests devient vite répétitif et chronophage :
- ✍️ Répétition du même code pour chaque vue
- 🔄 Copier-coller de fixtures et de setup
- 🐛 Oublis fréquents de cas de test importants
- ⏱️ Perte de temps sur du code boilerplate au lieu de tester la logique métier
La solution
Django AutoTest génère automatiquement vos tests à partir d'une configuration déclarative :
- ⚡ Gain de temps massif : 90% de code en moins à écrire
- 🎯 Tests exhaustifs : Le framework teste automatiquement tous les cas standards
- 🔧 Extensible : Ajoutez vos tests personnalisés quand nécessaire
- 🌍 Multilingue : Messages d'erreur en français ou anglais
- 🧪 Fixtures automatiques : Génération intelligente de données de test
✨ Fonctionnalités
✅ Ce que Django AutoTest fait AUJOURD'HUI
🎨 Génération automatique de tests
- Tests pour ListView, DetailView, CreateView, UpdateView, DeleteView
- Tests pour Function-Based Views (FBV)
- Tests GET, POST, PUT, PATCH, DELETE, HEAD
- Tests de status codes (200, 302, 404, etc.)
- Tests de contexte et de champs de réponse
🏭 ModelFactory intelligent
- Génération automatique de données de test valides
- Support des ForeignKey, OneToOneField, ManyToMany
- Gestion des champs uniques (email, username, etc.)
- Gestion des contraintes d'intégrité avec retry automatique
- Création d'utilisateurs Django pour l'authentification
- Cache intelligent pour éviter les doublons
📝 Validation de formulaires
- Test des champs requis (required_fields)
- Test des champs uniques (unique_fields)
- Test des types de données (type_fields)
- Test des longueurs min/max (len_fields)
- Test des champs facultatifs (optional_fields)
- Test des champs interdits (exclude_fields)
- Tests inverses (champs manquants → erreur attendue)
🔐 Authentification
- Support des vues avec
LoginRequiredMixin - Création automatique d'utilisateur de test
- Login/logout automatique selon la config
🌍 Multilingue
- Messages d'erreur en français ou anglais
- Configuration simple :
lang="fr"oulang="en"
🧩 Tests personnalisés
- Ajout facile de tests custom via
custom_tests - Accès aux fixtures créées automatiquement
- Combinaison avec les tests auto-générés
📊 Déduction intelligente
- Analyse automatique des vues Django génériques
- Extraction des champs du modèle
- Activation automatique des méthodes HTTP appropriées
- Status codes prédits selon le type de vue
📦 Installation
Prérequis
- Python 3.10+
- Django 4.0+
Installation depuis le dépôt
# Cloner le projet
git clone https://github.com/votre-username/django-autotest.git
# Installer les dépendances
cd django-autotest
pip install -r requirements.txt
# Intégrer dans votre projet Django
cp -r djangoautotest_app /path/to/your/project/
Ajout à INSTALLED_APPS
# settings.py
INSTALLED_APPS = [
# ...
'djangoautotest_app',
]
⚡ Utilisation rapide
Exemple 1 : Test d'une ListView
from djangoautotest_app.core.configs import AutoTestCaseConfig
from djangoautotest_app.core.testcase import AutoTestCase
from myapp.views import ProductListView
class ProductListViewTest(AutoTestCase):
config = AutoTestCaseConfig(
config={
"view": ProductListView,
"url_name": "product-list",
"fixtures": [
{
"model": Product,
"object_name": "products",
"count": 10
}
],
"method_allowed": {
"GET": {
"enabled": True,
"response": {
"status_code": 200,
"expected_fields": ["products", "page_obj"]
}
}
}
}
)
Résultat : Test automatique de la requête GET, vérification du status 200, présence des champs dans le contexte, et 10 produits créés automatiquement.
Exemple 2 : Test d'un CreateView avec formulaire
class ProductCreateViewTest(AutoTestCase):
config = AutoTestCaseConfig(
lang="fr", # Messages en français
config={
"view": ProductCreateView,
"url_name": "product-create",
"method_allowed": {
"POST": {
"enabled": True,
"auth_required": True, # Nécessite authentification
"inverse_test": True, # Active le test avec champs manquants
"request": {
"required_fields": ["name", "price", "category"],
"unique_fields": ["name"],
"len_fields": [
{"field": "name", "min": 3, "max": 100}
],
"type_fields": [
{"field": "price", "type": float}
]
},
"response": {
"status_code": 302, # Succès → redirection
"inverse_status_code": 400 # Échec → erreur
}
}
}
}
)
Résultat :
- Test POST avec tous les champs → succès (302)
- Test POST sans champs requis → échec (400)
- Test de l'unicité du nom
- Test des longueurs et types
- Utilisateur créé et connecté automatiquement
📚 Exemples détaillés
CreateView avec tests personnalisés
class UserRegistrationTest(AutoTestCase):
config = AutoTestCaseConfig(
config={
"view": UserRegistrationView,
"url_name": "register",
"method_allowed": {
"POST": {
"enabled": True,
"request": {
"required_fields": ["username", "email", "password"],
"len_fields": [
{"field": "password", "min": 8}
]
}
}
}
},
custom_tests=[
# Test personnalisé : vérifier que les emails en double sont refusés
lambda self: self._test_duplicate_email()
]
)
def _test_duplicate_email(self):
"""Test custom : l'email doit être unique."""
# Créer un premier utilisateur
data = {"username": "user1", "email": "test@test.com", "password": "12345678"}
self.client.post(reverse('register'), data=data)
# Tentative avec le même email
data2 = {"username": "user2", "email": "test@test.com", "password": "87654321"}
response = self.client.post(reverse('register'), data=data2)
self.assertEqual(response.status_code, 400)
self.assertIn('email', response.context['form'].errors)
UpdateView avec fixture
class ProductUpdateTest(AutoTestCase):
config = AutoTestCaseConfig(
config={
"view": ProductUpdateView,
"url_name": "product-update",
"fixtures": [
{
"model": Product,
"object_name": "product",
"count": 1,
"create_kwargs": {
"name": "Initial Product",
"price": 19.99
}
}
],
"method_allowed": {
"GET": {
"enabled": True,
"response": {
"status_code": 200,
"expected_fields": ["form", "object"]
}
},
"POST": {
"enabled": True,
"request": {
"required_fields": ["name", "price"]
},
"response": {
"status_code": 302
}
}
}
}
)
# Accès facile à la fixture créée
def test_product_name_updated(self):
"""Test personnalisé : vérifier que le nom est bien modifié."""
old_name = self.product_0.name
data = {"name": "Updated Product", "price": 29.99}
url = reverse('product-update', kwargs={'pk': self.product_0.pk})
self.client.post(url, data=data)
self.product_0.refresh_from_db()
self.assertNotEqual(self.product_0.name, old_name)
self.assertEqual(self.product_0.name, "Updated Product")
🏗️ Architecture
Django AutoTest se compose de 3 modules principaux :
1. ModelFactory (models.py)
Génère des données de test intelligentes et valides.
factory = ModelFactory(max_depth=5, create_m2m=True)
# Créer un produit avec toutes ses relations
product = factory.create(Product)
# → Crée automatiquement la catégorie, le fournisseur, etc.
# Créer un utilisateur
user = factory.create_user(username="testuser")
Fonctionnalités :
- Génération de données fake réalistes (via Faker)
- Support ForeignKey, OneToOne, ManyToMany
- Gestion des champs uniques avec retry
- Cache pour éviter les doublons
- Gestion des contraintes d'intégrité
2. AutoTestCaseConfig (configs.py)
Configuration déclarative des tests.
config = AutoTestCaseConfig(
lang="fr",
test_name="mon_test",
test_description="Description du test",
config={
"view": MyView,
"url_name": "my-url",
"fixtures": [...],
"method_allowed": {
"GET": {...},
"POST": {...}
}
},
custom_tests=[...]
)
Fonctionnalités :
- Validation de la configuration
- Déduction automatique depuis les vues génériques
- Fusion intelligente de configs
- Messages multilingues
3. AutoTestCase (testcase.py)
Génération dynamique de méthodes de test.
class MyViewTest(AutoTestCase):
config = AutoTestCaseConfig(...)
Fonctionnalités :
- Génération via
__init_subclass__ - Création automatique de méthodes
test_* - Assertions complètes
- Support JSON et TemplateResponse
- Client authentifié ou non
⚙️ Configuration complète
Structure de configuration
{
"view": MaVue, # Vue Django à tester
"url_name": "mon-url", # Nom de l'URL Django
"fixtures": [ # Données de test à créer
{
"model": MonModel,
"object_name": "objects",
"count": 5,
"create_kwargs": {...}, # Valeurs imposées (facultatif)
"factory_kwargs": {...}, # Config ModelFactory (facultatif)
"store": True # Stocker sur self (facultatif)
}
],
"method_allowed": {
"GET": {
"enabled": True, # Activer le test GET
"auth_required": False, # Authentification requise
"request": {
"query_params": {}, # Paramètres ?page=1
"headers": {} # Headers HTTP
},
"response": {
"status_code": 200, # Code attendu
"expected_fields": [], # Champs requis dans la réponse
"forbidden_fields": [], # Champs interdits
"expected_values": {}, # Valeurs exactes attendues
"content_type": "text/html" # Type de contenu
}
},
"POST": {
"enabled": True,
"auth_required": True,
"inverse_test": True, # Activer test avec champs manquants
"request": {
"required_fields": [], # Champs obligatoires
"optional_fields": [], # Champs facultatifs
"exclude_fields": [], # Champs interdits
"len_fields": [ # Contraintes de longueur
{"field": "name", "min": 3, "max": 50}
],
"type_fields": [ # Types attendus
{"field": "price", "type": float}
],
"unique_fields": [], # Champs uniques
"default_values": {} # Valeurs par défaut
},
"response": {
"status_code": 302,
"inverse_status_code": 400 # Code si champs manquants
}
}
}
}
Options de langue
# Messages en français (par défaut)
config = AutoTestCaseConfig(lang="fr", ...)
# Messages en anglais
config = AutoTestCaseConfig(lang="en", ...)
🌍 Multilingue (FR/EN)
Django AutoTest supporte le français et l'anglais pour tous les messages d'erreur.
Messages d'assertion
| Situation | Français | English |
|---|---|---|
| Status code incorrect | Code de statut attendu 200, obtenu 404 |
Expected status code 200, got 404 |
| Champ manquant | Champ attendu "username" non trouvé |
Expected field "username" not found |
| Champ interdit | Champ interdit "password" trouvé |
Forbidden field "password" found |
| Longueur invalide | La longueur 2 du champ "name" est inférieure au minimum 3 |
Field "name" length 2 is less than minimum 3 |
Exemple
# Config en français
class TestFR(AutoTestCase):
config = AutoTestCaseConfig(
lang="fr",
config={...}
)
# Output : "Code de statut attendu 200, obtenu 404"
# Config en anglais
class TestEN(AutoTestCase):
config = AutoTestCaseConfig(
lang="en",
config={...}
)
# Output: "Expected status code 200, got 404"
🤝 Contribuer
Toutes les contributions sont les bienvenues ! Voici comment participer :
1. Fork et clone
git clone https://github.com/alzeph/Django-Auto-Test.git
cd Django-Auto-Test
2. Créer une branche
git checkout -b feature/ma-nouvelle-fonctionnalite
3. Faire vos modifications
- Ajoutez vos fonctionnalités
- Écrivez des tests
- Documentez votre code
4. Soumettre une Pull Request
git add .
git commit -m "Ajout de ma fonctionnalité"
git push origin feature/ma-nouvelle-fonctionnalite
Puis ouvrez une PR sur GitHub avec une description claire.
Code style
- Suivre PEP 8
- Docstrings en français et anglais
- Type hints quand possible
- Tests unitaires obligatoires
🐛 Issues & Roadmap
🔴 Issues critiques (HELP WANTED!)
Voici les problèmes qui me bloquent actuellement. Si vous pouvez aider, vos PRs sont les bienvenues !
1. Bug dans les tests inverses
Problème : Les tests inverses (avec champs manquants) ne font actuellement rien (pass).
Fichier : djangoautotest_app/core/testcase.py, méthode _make_request()
Code actuel :
# Cas inverse : on enlève volontairement les champs requis
else:
pass # ❌ PROBLÈME : Rien n'est testé !
Ce qu'il faudrait :
- Retirer seulement UN champ requis (pas tous)
- Vérifier que la requête échoue avec le bon status code
- Vérifier que le message d'erreur est présent
Difficulté : Facile
Fonctionnalités manquantes
Difficulté : Moyen
1. Validation des choix (choices) 🚧
Besoin : Tester que les valeurs font partie des choix autorisés
Config souhaitée :
"choice_fields": [
{
"field": "status",
"choices": ["draft", "published", "archived"]
}
]
Difficulté : Moyen
8. Tests unitaires du framework 🧪
Problème : Le framework n'a pas de tests pour lui-même !
Ce qu'il faudrait :
- Tests unitaires pour
ModelFactory - Tests unitaires pour
AutoTestCaseConfig - Tests unitaires pour
AutoTestCase - Coverage > 90%
Outils : pytest, pytest-django, pytest-cov
Difficulté : 🔴 Difficile
9. Documentation complète 📚
Problème : Pas de documentation Read The Docs
Ce qu'il faudrait :
- Guide d'installation détaillé
- Tutoriels pas à pas
- Exemples pour chaque type de vue
- API Reference
- Contributing guide
Outils : Sphinx, Read The Docs
Difficulté : Moyen
10. Publication sur PyPI 📦
Problème : Installation manuelle uniquement
Ce qu'il faudrait :
- Créer
setup.py/pyproject.toml - Configurer versioning (semantic versioning)
- Publier sur PyPI :
pip install django-autotest - CI/CD avec GitHub Actions
Difficulté : Moyen
💡 Idées pour le futur
- Support des formsets Django
- Support des forms avec fichiers (FileField, ImageField)
- Support des vues AJAX
- Support des API REST (DRF)
- Génération de rapports HTML de tests
- Intégration avec coverage.py
- Plugin pytest pour utiliser sans TestCase
- Interface admin pour visualiser la couverture de tests
📄 Licence
MIT License
Copyright (c) 2025 [Votre Nom]
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
🙏 Remerciements
- Django pour le framework web
- Faker pour la génération de données
- La communauté Django pour l'inspiration
- Tous les contributeurs qui améliorent ce projet
📧 Contact
- Issues : GitHub Issues
- Discussions : GitHub Discussions
- Email : hervecedricyouan@gmail.com
⭐ Si ce projet vous aide, n'hésitez pas à lui donner une étoile sur GitHub ! ⭐
Made with ❤️ by [Votre Nom]
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_autotest_all-0.1.0.tar.gz.
File metadata
- Download URL: django_autotest_all-0.1.0.tar.gz
- Upload date:
- Size: 25.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f80eb7dba9b3739bba6df39545cd717f286c4ba8393b5f5bd2d29dfd0aa28c4
|
|
| MD5 |
2aeb397d40356da708ec5db75f9df608
|
|
| BLAKE2b-256 |
c38daf2c533a208d29642ad2ad2c9139ea4a15a304a046cf5638d4782eeb37db
|
File details
Details for the file django_autotest_all-0.1.0-py3-none-any.whl.
File metadata
- Download URL: django_autotest_all-0.1.0-py3-none-any.whl
- Upload date:
- Size: 21.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
72b6211618c21e21ede0ad1ef61e29ec1609eebc534ac4bcec07d96c1412d2ed
|
|
| MD5 |
44d85ef48288544de96bdd771c28601b
|
|
| BLAKE2b-256 |
66db275ee62909b4ebd514a70db700fc3dd7bc14d35ebfb4578c145d850b3f0d
|