main.py comptait 829 lignes et regroupait 9 domaines fonctionnels. Il ne fait plus que l'assemblage de l'application (configuration, middlewares, montage des routeurs), soit 115 lignes. - routers/ : un module par domaine, chacun déclarant sa propre dépendance d'authentification - domain.py : enums UserRole et AuditAction, mapping MONITO_TABLES ; les rôles étaient jusqu'ici répétés en dur à deux endroits - helpers.py : conversion des lignes pyodbc, écriture du journal - rate_limit.py : limiteur partagé, isolé pour éviter un import circulaire entre main.py et le routeur d'authentification Les codes HTTP littéraux (404, 401, 400, 201) passent aux constantes fastapi.status, comme le faisait déjà auth.py. Les actions du journal d'audit passent en paramètre SQL au lieu d'être concaténées. Aucune route modifiée : la comparaison des specs OpenAPI avant/après confirme que les 26 URL existantes sont identiques. conftest patchait main.get_cursor ; chaque routeur important désormais get_cursor dans son propre espace de noms, la fixture remplace le nom dans tous les modules concernés.
74 lines
1.7 KiB
Python
74 lines
1.7 KiB
Python
"""Fixtures de test : client FastAPI + curseur SQL simulé (aucune vraie BDD)."""
|
|
import os
|
|
from contextlib import contextmanager
|
|
|
|
os.environ.setdefault("JWT_SECRET", "test-secret")
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
import main
|
|
from auth import create_access_token
|
|
from routers import (
|
|
admin,
|
|
authentification,
|
|
dashboard,
|
|
evolution,
|
|
historique,
|
|
monitorings,
|
|
referentiels,
|
|
rgpd,
|
|
)
|
|
|
|
# Modules qui ont fait `from config import get_cursor` : l'import lie le nom
|
|
# dans leur propre espace de noms, il faut donc le remplacer dans chacun.
|
|
MODULES_AVEC_CURSEUR = (
|
|
main, admin, authentification, dashboard, evolution,
|
|
historique, monitorings, referentiels, rgpd,
|
|
)
|
|
|
|
|
|
class FakeCursor:
|
|
"""Curseur pyodbc simulé : on règle description / rows / one par test."""
|
|
def __init__(self):
|
|
self.description = []
|
|
self._rows = []
|
|
self._one = None
|
|
self.rowcount = 1
|
|
self.executed = []
|
|
|
|
def execute(self, query, *args):
|
|
self.executed.append((query, args))
|
|
return self
|
|
|
|
def fetchall(self):
|
|
return self._rows
|
|
|
|
def fetchone(self):
|
|
return self._one
|
|
|
|
|
|
@pytest.fixture
|
|
def cur(monkeypatch):
|
|
c = FakeCursor()
|
|
|
|
@contextmanager
|
|
def fake_get_cursor():
|
|
yield c
|
|
|
|
for module in MODULES_AVEC_CURSEUR:
|
|
if hasattr(module, "get_cursor"):
|
|
monkeypatch.setattr(module, "get_cursor", fake_get_cursor)
|
|
return c
|
|
|
|
|
|
@pytest.fixture
|
|
def client():
|
|
return TestClient(main.app)
|
|
|
|
|
|
@pytest.fixture
|
|
def auth_headers():
|
|
token = create_access_token({"sub": "admin", "role": "Admin", "uid": 1})
|
|
return {"Authorization": f"Bearer {token}"}
|