vendredi 25 septembre 2026

À propos

Contact

Tests

Test contractuel : figer le schéma d’une réponse REST pour de bon

Un front tiers consomme votre API REST WordPress. Un test contractuel garantit qu'aucune modification côté serveur ne casse silencieusement ce contrat.

Par Clément Hadrot • 19 décembre 2021 • 5 min de lecture • Aucun commentaire
Test contractuel : figer le schéma d'une réponse REST pour de bon

Une agence sœur développe une application mobile qui consomme le point de terminaison /wp-json/catalogue/v1/produits exposé par une extension que nous maintenons. Un jour, une modification apparemment anodine — renommer prix_ttc en prix_ttc_centimes pour clarifier l’unité — a fait planter l’application mobile en production, sans qu’aucun test côté WordPress n’ait rien détecté : tous les tests fonctionnels passaient, puisqu’ils ne vérifiaient que la présence d’un prix, jamais son nom de champ exact.

C’est exactement le problème que le test de contrat est censé résoudre : garantir qu’une réponse d’API respecte un schéma stable dans le temps, indépendamment de la logique métier qui la produit.

Ce qu’est réellement un test de contrat

Un test de contrat ne vérifie pas que les données retournées sont correctes au sens métier — c’est le rôle des tests fonctionnels classiques. Il vérifie que la forme de la réponse reste compatible avec ce qu’un consommateur externe attend : les champs présents, leur type, et leur imbrication. Deux applications peuvent avoir un contrat très différent de rigueur :

  • Un contrat « consumer-driven », où c’est le consommateur (l’application mobile, ici) qui définit et fournit le schéma attendu.
  • Un contrat « producer-driven », plus simple à mettre en place côté WordPress, où c’est l’équipe qui maintient l’API qui fige elle-même le schéma qu’elle s’engage à respecter.

Sur ce projet, faute d’accès direct au code de l’application mobile, l’option producer-driven a été retenue : le schéma est décrit et versionné directement dans le dépôt de l’extension WordPress.

Fonctionnement interne : comparer une réponse à un schéma de référence

Le principe technique est proche d’un test de non-régression appliqué à la structure plutôt qu’au contenu. On génère une réponse réelle, puis on la compare à un schéma figé, sans comparer les valeurs elles-mêmes :

public function test_contrat_endpoint_produits_stable(): void {
    $this->factory()->post->create(['post_type' => 'produit']);

    $requete = new WP_REST_Request('GET', '/catalogue/v1/produits');
    $reponse = rest_get_server()->dispatch($requete)->get_data();

    $premier_produit = $reponse[0];

    $this->assertArrayHasKey('id', $premier_produit);
    $this->assertIsInt($premier_produit['id']);
    $this->assertArrayHasKey('nom', $premier_produit);
    $this->assertIsString($premier_produit['nom']);
    $this->assertArrayHasKey('prix_ttc', $premier_produit);
    $this->assertIsFloat($premier_produit['prix_ttc']);
    $this->assertArrayNotHasKey('prix_ttc_centimes', $premier_produit);
}
L'essentiel à retenir : Le contrat protège le consommateur, pas seulement le producteur ; Un champ retiré casse autant qu'un champ mal typé ; Le test de contrat vit côté producteur de l'API

Ce test échoue immédiatement si prix_ttc disparaît, change de type, ou si son nom est modifié — exactement le scénario qui avait cassé l’application mobile. La dernière assertion négative est volontaire : elle empêche une renomination silencieuse qui ajouterait un nouveau champ sans retirer l’ancien proprement.

Cas d’usage typiques

Le test de contrat prend tout son sens dans trois situations récurrentes en agence : une API consommée par une application mobile dont le cycle de publication est plus lent que celui du site WordPress, une intégration avec un système tiers (CRM, ERP) maintenu par une autre équipe, ou une API publique documentée que des clients externes intègrent eux-mêmes sans qu’on connaisse leur code.

Pièges à éviter

  • Un schéma trop strict, qui interdit l’ajout de tout nouveau champ, bloque l’évolution légitime de l’API — en général, ajouter un champ est un changement compatible, le retirer ou le renommer ne l’est pas.
  • Un test de contrat qui vérifie aussi les valeurs métier mélange deux responsabilités et devient fragile pour de mauvaises raisons — garder les deux préoccupations dans des tests séparés.
  • Oublier de tester les réponses d’erreur (404, 403) fait perdre une partie du contrat : un consommateur externe a besoin de codes d’erreur stables autant que de champs stables.

Un champ retiré d’une réponse API ne casse jamais rien du côté qui le retire — il casse toujours ailleurs, chez quelqu’un qui ne lira pas le message de commit qui l’a supprimé.

Notion voisine à ne pas confondre

Ce principe de contrat figé ne doit pas être confondu avec la validation par schéma JSON formel (JSON Schema), qui définit précisément les règles de validation d’une charge utile côté serveur au moment de la requête — une pratique différente, traitée séparément, qui répond à un besoin de validation des entrées plutôt qu’à un besoin de non-régression sur les sorties.

En résumé

Un test de contrat n’a pas besoin d’outillage sophistiqué pour apporter de la valeur : quelques assertions sur les clés et les types d’une réponse REST suffisent à intercepter la classe de régression la plus coûteuse pour un consommateur externe — celle qui ne se voit jamais dans les tests fonctionnels internes, mais qui casse une application tierce sans le moindre avertissement.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi