# Tests de contrat entre une extension et un CRM : figer le format sortant

> Une recette pour figer le format des requêtes envoyées à HubSpot ou Salesforce et détecter tout changement silencieux d'une version à l'autre de l'extension.

- Auteur : WordPress Développement
- Publié le : 2024-09-05
- Mis à jour le : 2024-09-05
- Catégorie : Tests
- URL : https://www.wpmoderne.fr/tests/tests-contrat-extension-crm-format-sortant/

## L’essentiel

- Figer le corps de requête avec un fichier de référence versionné
- Détecter un changement de format dès la revue de code
- Distinguer un changement voulu d'une régression

« Les tests de contrat vérifient que les deux parties d'une intégration respectent un accord partagé sur le format des données échangées », rappelle la documentation de référence sur le sujet côté écosystème PHP. Pour une extension WordPress qui pousse des contacts vers Salesforce ou HubSpot, cet accord se résume souvent à une question simple : le corps JSON envoyé change-t-il de forme sans que personne ne s'en aperçoive ?

Ce risque s'est concrétisé sur une extension maison de synchronisation CRM, quand une refactorisation apparemment anodine du code de construction de la charge utile a supprimé silencieusement un champ obligatoire côté Salesforce, provoquant un rejet de synchronisation détecté trois jours plus tard seulement, via les logs d'erreur du CRM.

## Le problème : un format qui évolue sans garde-fou

Le code de construction de la charge utile assemblait un tableau PHP converti en JSON avant l'envoi. Rien dans la suite de tests existante ne vérifiait la forme exacte de ce tableau : les tests unitaires en place se contentaient de vérifier que la fonction ne levait pas d'exception, sans jamais inspecter le contenu produit.

```
function build_salesforce_payload( WP_User $user ): array {
    return array(
        'FirstName' => $user->first_name,
        'LastName'  => $user->last_name,
        'Email'     => $user->user_email,
        'Company'   => get_user_meta( $user->ID, 'entreprise', true ),
        'Phone'     => get_user_meta( $user->ID, 'telephone', true ),
        'LeadSource' => 'Site WordPress',
        'Industry'  => get_user_meta( $user->ID, 'secteur', true ),
    );
}
```

## Le snippet commenté : figer le format avec un fichier de référence

> L'essentiel à retenir : Figer le corps de requête avec un fichier de référence versionné ; Détecter un changement de format dès la revue de code ; Distinguer un changement voulu d'une régression

La technique retenue reprend le principe des golden files, adapté ici au format d'une charge utile plutôt qu'à un export complet. Un fichier JSON de référence, versionné avec le code, décrit la forme exacte attendue. Le test compare la sortie de la fonction à ce fichier et échoue au moindre écart de structure.

```
public function test_payload_matches_contract(): void {
    $user    = $this->create_test_user();
    $payload = build_salesforce_payload( $user );

    $reference = json_decode(
        file_get_contents( __DIR__ . '/contracts/salesforce-contact.json' ),
        true
    );

    $this->assertSame(
        array_keys( $reference ),
        array_keys( $payload ),
        'La liste des champs envoyés à Salesforce a changé'
    );
}
```

Ce test compare volontairement les clés du tableau plutôt que les valeurs elles-mêmes, puisque les valeurs varient légitimement d'un utilisateur à l'autre. Ce qui doit rester stable, c'est la forme du contrat : quels champs sont envoyés, sous quel nom exact, dans quelle structure.

### Documenter chaque changement de contrat volontaire

Quand un changement de format est réellement voulu, par exemple l'ajout d'un nouveau champ personnalisé demandé par le client, le fichier de référence est mis à jour dans la même Pull Request que le code, avec une explication dans le message de commit. Cette convention transforme un fichier de référence en historique lisible des évolutions du contrat, consultable par n'importe quel développeur qui rejoint le projet.

## Variante : un contrat par CRM cible

L'extension pousse des contacts vers deux CRM différents selon la configuration du client, HubSpot ou Salesforce, chacun avec ses propres conventions de nommage de champs. Deux fichiers de contrat distincts coexistent donc, chacun testé indépendamment, pour éviter qu'une modification pensée pour l'un des deux CRM n'affecte silencieusement l'autre par un code partagé mal isolé.

- `contracts/salesforce-contact.json` pour la structure attendue par Salesforce
- `contracts/hubspot-contact.json` pour la structure attendue par HubSpot, avec ses propriétés personnalisées préfixées
- Un test de non-régression qui vérifie qu'aucun champ commun ne diverge entre les deux formats sans raison documentée

## Limites de cette approche

Un test de contrat de ce type ne remplace pas un test d'intégration réel contre une instance de bac à sable du CRM, seul capable de vérifier que le format accepté côté test correspond réellement à ce qu'attend l'API en production. Il agit plutôt comme un premier filet, rapide à exécuter, qui intercepte l'immense majorité des régressions de format avant même d'atteindre l'étape d'intégration plus coûteuse en temps.

> Un test de contrat ne garantit pas qu'une intégration fonctionne : il garantit qu'elle continue de parler le même langage qu'hier.

## Pour aller plus loin

Cette recette se limite volontairement aux formats de données échangés entre l'extension et les CRM tiers. Les tests de contrat déjà publiés côté API REST interne de l'agence répondent à une problématique voisine mais distincte, celle de la stabilité d'une interface exposée à d'autres équipes internes plutôt qu'à un service tiers.
