### **9. Tests et Qualité**

Il n'y a pas d'objectif de couverture. Chaque logique non triviale laisse derrière elle la plus petite chose qui échoue si cette logique se casse, et rien de plus. Un test qui ne peut pas échouer est du code mort déguisé en assurance.

#### **9.1. Stratégie par brique**

| Brique | Ce qui est testé, et comment |
| --- | --- |
| `contracts` | Les cas limites des schémas : branchement vers une étape inexistante, étape sans cible alors que son type en exige une, option sans libellé |
| `sdk` | La résolution de cible sur DOM simulé, la machine d'exécution et le calcul du TTL en tests unitaires ; le rendu, le positionnement, l'isolation et le clavier dans un navigateur réel |
| `extension` | La génération des candidats sur DOM simulé, y compris le contrôle de stabilité des identifiants ; un parcours complet de capture et publication dans un navigateur réel |
| `api` | Tests d'intégration sur une véritable base PostgreSQL en conteneur, sans simulacre |
| `dashboard` | Un unique test de bout en bout vérifiant que les écrans s'affichent et que les données arrivent |

**La base de données n'est jamais simulée.** Les garanties qui nous intéressent, à savoir les contraintes, les cascades et l'unicité de la version publiée, sont précisément celles qu'un simulacre supprime. Un test qui remplace PostgreSQL par un objet factice vérifie que le code appelle les bonnes fonctions, pas que les données restent cohérentes.

**Le test le plus important du backend** est celui du cloisonnement entre organisations (section 2.5) : il vérifie qu'aucune route d'administration ne laisse une organisation atteindre les données d'une autre, y compris en fournissant un identifiant valide appartenant à autrui. Il est écrit une fois par entité exposée, et il n'est pas négociable.

#### **9.2. Banc d'essai de la résilience**

C'est le dispositif qui mesure le différenciateur produit, et sans lequel la promesse d'auto-healing resterait une affirmation.

Le dépôt contient un jeu de pages de référence décliné en trois générations, simulant l'évolution d'une application cliente :

| Génération | Transformation appliquée |
| --- | --- |
| 1 | Page d'origine, sur laquelle les sélecteurs sont capturés |
| 2 | Classes renommées, identifiants régénérés, arbre remanié, attributs de test conservés |
| 3 | Attributs de test retirés, libellés reformulés, structure profondément modifiée |

Le test capture les candidats sur la première génération, puis vérifie leur résolution sur les suivantes. Il produit un **taux de survie des sélecteurs** par génération, suivi dans le temps comme un indicateur produit.

Les seuils de sortie sont explicites : la deuxième génération doit être résolue intégralement, faute de quoi la stratégie de candidats est défaillante et non l'application cliente. La troisième sert de mesure, sans seuil bloquant : elle décrit ce que le produit sait encore rattraper quand le site n'offre plus aucun repère stable, et alimente le discours commercial sur l'intérêt des attributs de test.

#### **9.3. Intégration continue**

Une seule chaîne, exécutée sur chaque proposition de modification :

1. Installation depuis le fichier de verrouillage.
2. Formatage et lint, incluant la règle d'import du SDK de la section 1.3.
3. Vérification des types sur l'ensemble du monorepo.
4. Tests unitaires.
5. Compilation des quatre briques.
6. **Mesure du poids du SDK compressé**, bloquante au-delà du seuil de la section 3.1.
7. Tests de bout en bout, banc d'essai de résilience inclus.
8. Application à blanc des migrations sur une base vierge.

Sont bloquants : le lint, les types, les tests, le budget de poids et les migrations. La durée cible de l'ensemble est de dix minutes ; au-delà, la chaîne devient un obstacle que l'équipe apprend à contourner.
