mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 07:53:23 +00:00
Compare commits
1 Commits
7486f6c5ce
...
A64_TestsA
| Author | SHA1 | Date | |
|---|---|---|---|
| 0a2b23f260 |
2
Back-End/.gitignore
vendored
2
Back-End/.gitignore
vendored
@ -5,3 +5,5 @@ data
|
|||||||
*.dmp
|
*.dmp
|
||||||
staticfiles
|
staticfiles
|
||||||
/*/Configuration/application*.json
|
/*/Configuration/application*.json
|
||||||
|
rapport_tests_back.json
|
||||||
|
tests_automatiques.json
|
||||||
@ -70,3 +70,7 @@ xhtml2pdf==0.2.16
|
|||||||
channels==4.0.0
|
channels==4.0.0
|
||||||
channels-redis==4.1.0
|
channels-redis==4.1.0
|
||||||
daphne==4.1.0
|
daphne==4.1.0
|
||||||
|
pytest
|
||||||
|
djangorestframework
|
||||||
|
pytest-django
|
||||||
|
pytest-json-report
|
||||||
|
|||||||
39
Back-End/test_all_endpoints.py
Normal file
39
Back-End/test_all_endpoints.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
"""
|
||||||
|
Starter de tests automatiques pour valider tous les endpoints définis dans les fichiers urls.py du projet Django N3WT-SCHOOL.
|
||||||
|
Chaque endpoint est testé pour la réponse HTTP attendue (200, 401, 403, 404, etc.).
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
from django.urls import reverse, resolve
|
||||||
|
from rest_framework.test import APIClient
|
||||||
|
from django.conf import settings
|
||||||
|
from django.urls import get_resolver
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
class TestAllEndpoints:
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def setup(self):
|
||||||
|
self.client = APIClient()
|
||||||
|
|
||||||
|
def get_all_url_patterns(self):
|
||||||
|
resolver = get_resolver()
|
||||||
|
patterns = resolver.url_patterns
|
||||||
|
urls = []
|
||||||
|
def extract(patterns, prefix=""):
|
||||||
|
for p in patterns:
|
||||||
|
if hasattr(p, 'url_patterns'):
|
||||||
|
extract(p.url_patterns, prefix + str(p.pattern))
|
||||||
|
else:
|
||||||
|
urls.append(prefix + str(p.pattern))
|
||||||
|
extract(patterns)
|
||||||
|
return urls
|
||||||
|
|
||||||
|
def test_all_endpoints_anonymous(self):
|
||||||
|
urls = self.get_all_url_patterns()
|
||||||
|
for url in urls:
|
||||||
|
if '<' in url: # skip dynamic urls for starter
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
response = self.client.get(url)
|
||||||
|
assert response.status_code in [200, 401, 403, 404]
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Erreur sur {url}: {e}")
|
||||||
124
Back-End/test_auth_endpoints.py
Normal file
124
Back-End/test_auth_endpoints.py
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
"""
|
||||||
|
Tests automatiques pour les endpoints Auth de l'API N3WT-SCHOOL.
|
||||||
|
- Teste les endpoints GET, y compris dynamiques.
|
||||||
|
- Teste l'authentification (login JWT) et l'accès aux endpoints protégés.
|
||||||
|
- Vérifie la structure JSON des réponses principales.
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
from django.urls import reverse
|
||||||
|
from rest_framework.test import APIClient
|
||||||
|
from Auth.models import Profile, ProfileRole
|
||||||
|
from Establishment.models import Establishment
|
||||||
|
from django.contrib.auth.hashers import make_password
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
class TestAuthEndpoints:
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def setup(self, db):
|
||||||
|
self.client = APIClient()
|
||||||
|
# Création d'un établissement de test
|
||||||
|
self.establishment = Establishment.objects.create(
|
||||||
|
name="Etablissement Test",
|
||||||
|
address="1 rue du test",
|
||||||
|
total_capacity=100,
|
||||||
|
establishment_type=[1],
|
||||||
|
evaluation_frequency=1,
|
||||||
|
licence_code="LIC123",
|
||||||
|
is_active=True
|
||||||
|
)
|
||||||
|
# Création d'un utilisateur de test
|
||||||
|
self.test_email = 'testuser@example.com'
|
||||||
|
self.test_password = 'testpass123'
|
||||||
|
self.profile = Profile.objects.create(
|
||||||
|
email=self.test_email,
|
||||||
|
username=self.test_email,
|
||||||
|
password=make_password(self.test_password)
|
||||||
|
)
|
||||||
|
self.profile_role = ProfileRole.objects.create(
|
||||||
|
profile=self.profile,
|
||||||
|
role_type=1, # ADMIN
|
||||||
|
establishment=self.establishment,
|
||||||
|
is_active=True
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_csrf(self):
|
||||||
|
response = self.client.get('/Auth/csrf')
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert 'csrfToken' in response.json()
|
||||||
|
|
||||||
|
def test_login(self):
|
||||||
|
response = self.client.post('/Auth/login', {
|
||||||
|
'email': self.test_email,
|
||||||
|
'password': self.test_password
|
||||||
|
}, format='json')
|
||||||
|
assert response.status_code in [200, 401]
|
||||||
|
if response.status_code == 200:
|
||||||
|
assert 'access' in response.json() or 'token' in response.json()
|
||||||
|
|
||||||
|
def test_profiles(self):
|
||||||
|
# GET /Auth/profiles
|
||||||
|
response = self.client.get(f'/Auth/profiles')
|
||||||
|
assert response.status_code in [200, 401, 403]
|
||||||
|
if response.status_code == 200:
|
||||||
|
# Vérifie que le profil de test existe dans la liste
|
||||||
|
emails = [p.get('email') for p in response.json() if isinstance(p, dict)]
|
||||||
|
assert self.test_email in emails
|
||||||
|
|
||||||
|
def test_profiles_id(self):
|
||||||
|
# GET /Auth/profiles/<id>
|
||||||
|
response = self.client.get(f'/Auth/profiles/{self.profile.id}')
|
||||||
|
assert response.status_code in [200, 401, 403, 404]
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
assert data.get('email') == self.test_email
|
||||||
|
|
||||||
|
def test_profile_roles(self):
|
||||||
|
# GET /Auth/profileRoles avec paramètres requis
|
||||||
|
params = {
|
||||||
|
'establishment_id': self.establishment.id,
|
||||||
|
'filter': 'school'
|
||||||
|
}
|
||||||
|
response = self.client.get('/Auth/profileRoles', params)
|
||||||
|
assert response.status_code in [200, 401, 403, 400]
|
||||||
|
if response.status_code == 200:
|
||||||
|
results = response.json()
|
||||||
|
# Adapter à la structure réelle de la réponse : clé 'profilesRoles'
|
||||||
|
if isinstance(results, dict) and 'profilesRoles' in results:
|
||||||
|
results = results['profilesRoles']
|
||||||
|
found = any(
|
||||||
|
r.get('profile') == self.profile.id and r.get('role_type') == 1
|
||||||
|
for r in results if isinstance(r, dict)
|
||||||
|
)
|
||||||
|
assert found
|
||||||
|
|
||||||
|
def test_profile_roles_id(self):
|
||||||
|
# GET /Auth/profileRoles/<id>
|
||||||
|
response = self.client.get(f'/Auth/profileRoles/{self.profile_role.id}')
|
||||||
|
assert response.status_code in [200, 401, 403, 404]
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
assert data.get('profile') == self.profile.id
|
||||||
|
assert data.get('role_type') == 1
|
||||||
|
|
||||||
|
def test_reset_password(self):
|
||||||
|
# POST /Auth/resetPassword/<code> (méthode attendue)
|
||||||
|
response = self.client.post('/Auth/resetPassword/ABCDEF', {
|
||||||
|
'password1': 'newpass123',
|
||||||
|
'password2': 'newpass123'
|
||||||
|
}, format='json')
|
||||||
|
assert response.status_code in [200, 400, 404]
|
||||||
|
# 400 attendu si le code est invalide ou expiré
|
||||||
|
|
||||||
|
def test_info_session(self):
|
||||||
|
# GET /Auth/infoSession (protégé)
|
||||||
|
login = self.client.post('/Auth/login', {
|
||||||
|
'email': self.test_email,
|
||||||
|
'password': self.test_password
|
||||||
|
}, format='json')
|
||||||
|
if login.status_code == 200 and ('access' in login.json() or 'token' in login.json()):
|
||||||
|
token = login.json().get('access') or login.json().get('token')
|
||||||
|
self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}')
|
||||||
|
response = self.client.get('/Auth/infoSession')
|
||||||
|
assert response.status_code in [200, 401, 403]
|
||||||
|
else:
|
||||||
|
pytest.skip('Impossible de s’authentifier pour tester infoSession')
|
||||||
59
docs/tests_automatiques.md
Normal file
59
docs/tests_automatiques.md
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Documentation des tests automatiques
|
||||||
|
|
||||||
|
Ce document décrit la structure et l’utilisation du starter de tests automatiques pour valider tous les endpoints exposés par les fichiers `urls.py` des applications Django du Back-End.
|
||||||
|
|
||||||
|
## Objectif
|
||||||
|
|
||||||
|
- Vérifier automatiquement que chaque route définie dans le projet répond bien à une requête HTTP (statut attendu : 200, 401, 403, 404).
|
||||||
|
- Permettre une validation rapide de la couverture des endpoints lors de chaque pipeline CI.
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
- Le fichier principal est `Back-End/test_all_endpoints.py`.
|
||||||
|
- Ce test utilise `pytest` et `pytest-django` pour parcourir toutes les routes du projet et effectuer une requête GET anonyme.
|
||||||
|
- Les routes dynamiques (avec paramètres) sont ignorées dans ce starter.
|
||||||
|
|
||||||
|
## Exécution
|
||||||
|
|
||||||
|
1. Installer les dépendances si besoin :
|
||||||
|
```sh
|
||||||
|
pip install pytest pytest-django djangorestframework
|
||||||
|
```
|
||||||
|
2. Lancer les tests :
|
||||||
|
```sh
|
||||||
|
pytest Back-End/test_all_endpoints.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Intégration CI
|
||||||
|
|
||||||
|
- Ajouter la commande de test dans votre pipeline CI (GitHub Actions, GitLab CI, Jenkins, etc.) :
|
||||||
|
```sh
|
||||||
|
pytest Back-End/test_all_endpoints.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Personnalisation
|
||||||
|
|
||||||
|
- Pour tester les routes nécessitant une authentification ou des paramètres, compléter le test avec des cas spécifiques.
|
||||||
|
- Pour chaque nouvelle route, le test s’exécutera automatiquement.
|
||||||
|
|
||||||
|
## Ajout
|
||||||
|
|
||||||
|
- Ajout d'un fichier de tests automatiques dédié à Auth (`test_auth_endpoints.py`) pour tester tous les endpoints Auth (GET, dynamiques, login JWT, accès protégé, structure JSON).
|
||||||
|
- Les tests créent un utilisateur et un profilRole de test, réalisent un login, et vérifient les accès aux endpoints principaux, y compris les routes dynamiques et protégées.
|
||||||
|
|
||||||
|
## Utilisation
|
||||||
|
|
||||||
|
- Lancer les tests avec :
|
||||||
|
```bash
|
||||||
|
pytest --json-report --json-report-file=tests_automatiques.json
|
||||||
|
```
|
||||||
|
- Le rapport inclura les résultats détaillés pour chaque endpoint Auth.
|
||||||
|
|
||||||
|
## Extension
|
||||||
|
|
||||||
|
- Étendre sur le même modèle pour les autres applications (School, Subscriptions, etc.)
|
||||||
|
- Ajouter des tests POST/PUT/DELETE et des cas d’erreur/permissions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Pour toute question ou évolution, se référer au ticket associé.
|
||||||
Reference in New Issue
Block a user