learn.chetana.fr

Tests et CI : la discipline qui tient le systĂšme

12 min de lectureEssentiel

La philosophie : intégration > mocks

La rÚgle du projet : tester contre de vraies dépendances plutÎt que des mocks. Les tests Python tournent sur un PostgreSQL réel jetable (testcontainers) et un fakeredis :

# le test d'isolation RLS le plus important du repo (en substance) :
async def test_rls_isolation(pg_container):
    async with session_with_tenant(factory, tenant_a):
        await create_variant(name="secret-A")
    async with session_with_tenant(factory, tenant_b):
        rows = await list_variants()
        assert rows == []          # le tenant B ne voit RIEN de A

Pourquoi c'est non nĂ©gociable ici : la RLS ne se mocke pas. Un mock de session validerait du code qui fuit en prod ; seul un vrai Postgres avec les vraies policies prouve l'isolation. MĂȘme logique pour la recherche hybride (tsvector, pg_trgm, HNSW : comportements rĂ©els uniquement). Config pytest stricte : asyncio_mode=auto, et filterwarnings=error — un warning EST un Ă©chec.

La pipeline GitLab : chaque invariant a son job

lint:python (ruff)        typecheck (mypy --strict/pkg)   arch:imports (import-linter)
arch:deps (deptry)        test:python (pytest+testcontainers, par package)
lint:web / test:web       test:e2e (Playwright)           secrets (gitleaks)
lint:sql (squawk)         deadcode (vulture)              sonarcloud

À retenir : l'architecture a ses propres jobs (arch:*) au mĂȘme rang que les tests. Et les hooks locaux vĂ©rifient les invariants mĂ©tier avant mĂȘme le commit : pas de WHERE tenant_id manuel, pas de schĂ©ma en dur, pas de commit sur main.

Deux renforts récents complÚtent le dispositif :

  • le Quality Gate SonarCloud est bloquant sur les MRs (couverture et code smells du new code — on ne juge que ce qu'on ajoute, la dette historique se rĂ©sorbe sĂ©parĂ©ment) ;
  • des suites E2E Playwright (Quotes, Mappings IA — ~35 scĂ©narios chacune) tournent contre l'environnement de dev dĂ©ployĂ© et publient leur rapport dans un canal Slack dĂ©diĂ©, avec le commit ET la version rĂ©ellement servie par l'env (pour dĂ©tecter les « dĂ©ploiements dĂ©calĂ©s »). Un Ă©chec E2E ping le canal : la recette est continue, pas Ă©vĂ©nementielle.

Le déploiement hybride

L'API part sur AWS ECR (release par tag semver, manuelle), le front Nuxt sur GCP Cloud Run — deux clouds, deux cadences, reliĂ©s par un repo de changelogs de dĂ©ploiement (ArgoCD cĂŽtĂ© prod). La release est un bouton conscient, pas un push automatique : sur un produit B2B, on choisit quand embarquer quoi.

Récap final du cours : le chemin complet

Tu peux maintenant suivre une requĂȘte de bout en bout : JWT Logto → tenant_id → session RLS (SET LOCAL) → service → LangGraph astream → SDK Anthropic streaming (caching, tools ReAct, model_view/ui_events) → recherche hybride RRF → SSE AG-UI → UI gĂ©nĂ©rative Nuxt — le tout tracĂ© dans Langfuse, gardĂ© par mypy/ruff/import-linter, testĂ© sur vrais conteneurs. C'Ă©tait la carte ; le territoire t'attend dans le repo. 🎓

đŸ§© Quiz1/3

Pourquoi la RLS DOIT ĂȘtre testĂ©e sur un vrai Postgres ?

🃏 Flashcards1/4