Vous livrez une petite modification à un point de terminaison. Le code compile, la nouvelle fonctionnalité fonctionne, et vous déployez. Deux jours plus tard, un client mobile commence à planter parce qu'un champ que vous avez renommé était une chaîne de caractères et est maintenant un objet. Personne n'avait l'intention de le casser. Le changement semblait local. Il ne l'était pas.
Les tests de régression d'API existent pour détecter ce type d'échec avant qu'il n'atteigne qui que ce soit. Vous enregistrez une suite de tests qui décrivent le comportement actuel de votre API, puis vous réexécutez cette suite à chaque modification. Lorsqu'une forme de réponse, un code de statut ou une valeur clé s'écarte de ce que vous avez enregistré, la suite échoue et vous indique exactement où. Ce guide couvre ce qu'il faut établir comme référence, comment construire une suite réutilisable et comment l'exécuter automatiquement en CI afin qu'un renommage ne devienne jamais un incident.
Qu'est-ce que le test de régression d'API (et pourquoi les API régressent)
Les tests de régression consistent à réexécuter des tests qui ont déjà réussi pour confirmer que le comportement existant est toujours maintenu après une modification. Pour les API, le « comportement existant » est le contrat sur lequel vos consommateurs s'appuient : les routes, les codes de statut, le schéma de réponse et les valeurs des champs clés.
Les API régressent pour des raisons ordinaires. Quelqu'un renomme un champ JSON. Une refactorisation change un 200 en 204. Une nouvelle règle de validation rejette une entrée qui était auparavant acceptée. Une mise à jour d'ORM modifie silencieusement le formatage des dates. Une mise à jour de dépendance altère un message d'erreur qu'un client analyse. Aucun de ces problèmes n'apparaît comme des erreurs de compilation. Ils se manifestent comme des intégrations rompues, et souvent seulement pour un sous-ensemble d'appelants.
La distinction importante ici : le test de régression d'API est plus étroit que le test de régression logiciel général. Vous ne revérifiez pas la logique métier de l'ensemble de l'application. Vous vérifiez que la surface HTTP, la partie à laquelle d'autres systèmes se couplent, n'a pas bougé. Cet accent est ce qui rend son exécution peu coûteuse à chaque commit.
Ce qu'il faut établir comme référence
Une suite de régression n'est efficace que par ce qu'elle affirme. Affirmer trop peu et de vraies ruptures passent inaperçues. Affirmer trop et chaque modification intentionnelle fait échouer la suite. Visez les champs qu'un consommateur remarquerait réellement.
Établissez ces quatre couches comme référence :
- Codes de statut. Chaque point de terminaison doit renvoyer un statut connu pour des entrées connues. Un
200qui devient un500, ou un201qui devient un200, est une régression même si le corps semble correct. - Schéma de réponse. La structure et les types de la réponse. Noms de champs, imbrication, et si une valeur est une chaîne de caractères, un nombre, un tableau ou un objet. La dérive de schéma est la rupture silencieuse la plus courante.
- Valeurs des champs clés. Pas toutes les valeurs, mais celles ayant une signification contractuelle : un
idqui doit être présent, un énumérateurstatusqui doit rester dans un ensemble connu, untotalqui doit être un nombre. - Contrats. La relation entre votre spécification OpenAPI et la réponse en direct. Si la spécification indique que
emailest requis et que l'API cesse de le renvoyer, il s'agit d'une violation de contrat. Voir tests de contrat d'API pour savoir comment faire de la spécification la source de vérité.
Une règle utile : affirmez ce qui ferait échouer un client, et non ce qui se trouve dans la charge utile aujourd'hui. Un horodatage createdAt change à chaque requête, donc fixez son type et son format, pas sa valeur.
Voici un ensemble minimal d'assertions pour un seul point de terminaison, écrites comme de simples vérifications que vous exécuteriez sur une réponse :
GET /v1/users/42 -> 200
body.id is present, type number
body.email is present, type string, matches email format
body.status is one of ["active", "pending", "suspended"]
body.roles type array
response time < 800 ms
Ces cinq lignes décrivent le contrat. Si l'une d'elles échoue après une modification, vous avez une régression. Pour un traitement plus approfondi de l'écriture de vérifications sur les corps de réponse, voir les assertions d'API.
Tests de régression manuels ou automatisés
Vous pouvez effectuer des tests de régression manuellement. Après une modification, vous ouvrez votre client API, rejouez une poignée de requêtes enregistrées et examinez les réponses. Cela fonctionne pour un point de terminaison et s'écroule à dix. Les humains sautent les cas ennuyeux, et ce sont justement là que se cachent les régressions. Les vérifications manuelles ne peuvent pas non plus s'exécuter à 2 heures du matin lorsqu'une tâche planifiée fusionne une mise à jour de dépendance.
Les tests de régression automatisés retirent l'humain de la boucle. Vous enregistrez la suite une fois, puis une machine la réexécute à chaque push, à chaque demande de tirage (pull request) et à chaque déploiement. La valeur n'est pas la vitesse d'une seule exécution. C'est que la suite s'exécute à chaque fois, sans que personne ne décide que l'effort en vaut la peine.
Le compromis est le travail initial. Vous devez construire la suite et la maintenir à jour. Ce coût de maintenance est réel, mais il est inférieur au coût d'un incident de production qu'un test de cinq secondes aurait pu détecter.
| Manuel | Automatisé | |
|---|---|---|
| S'exécute à chaque modification | Non, dépend de la discipline | Oui, par défaut |
| Couverture | Quelques points de terminaison | Toute la suite |
| Coût par exécution | Minutes de temps humain | Secondes de calcul |
| Détecte les pannes à 2h du matin | Non | Oui |
| Effort initial | Faible | Modéré |
Pour tout ce qui dépasse un projet de démonstration, automatisez-le.
Construire une suite de régression réutilisable
Une suite de régression est un ensemble de requêtes enregistrées, chacune avec des assertions, regroupées pour que vous puissiez les exécuter ensemble. L'objectif est la réutilisation : la construire une fois, l'exécuter indéfiniment, l'étendre lorsque vous ajoutez des points de terminaison.
Structurez la suite de manière à ce qu'elle survive aux changements :
Regroupez par ressource, pas par fonctionnalité. Mettez tous les tests /users ensemble, tous les tests /orders ensemble. Lorsque vous touchez le service des utilisateurs, vous savez quel groupe surveiller.
Utilisez des variables d'environnement pour tout ce qui est variable. L'URL de base, les jetons d'authentification et les identifiants de locataire (tenant IDs) appartiennent à un environnement, et ne doivent pas être codés en dur dans chaque requête. Cela permet à la même suite de s'exécuter contre les environnements local, de staging et de production en échangeant un seul paramètre.
Enchaînez les requêtes qui dépendent les unes des autres. Un flux réaliste crée une ressource, la relit, la met à jour et la supprime. Extrayez l'id de la réponse de création et passez-le à la requête suivante. Cela détecte les régressions qui n'apparaissent que dans une séquence, et non de manière isolée. C'est là que les tests de régression recoupent les tests d'intégration d'API.
Gérez les cas limites avec des données. Au lieu de dix requêtes presque identiques, écrivez une seule requête et alimentez-la avec un tableau d'entrées : valeurs valides, valeurs vides, valeurs limites et valeurs connues comme étant incorrectes. Chaque ligne devient un cas de test. Les tests basés sur les données maintiennent la suite petite tout en élargissant la couverture.
Voici à quoi pourrait ressembler un tableau de données pour un seul test de validation au format CSV :
email,expectedStatus
alice@example.com,201
bob@test.co,201
not-an-email,422
,422
a@b,422
Une requête, cinq cas, cinq assertions sur le code de statut. Ajoutez une ligne lorsque vous trouvez un nouveau cas limite, et la suite grandit sans nouveau code.
Gardez la suite rapide. Une suite de régression qui prend vingt minutes sera ignorée. Simulez les dépendances tierces lentes, exécutez les requêtes indépendantes en parallèle là où votre outil le permet, et réservez les flux de bout en bout complets pour une exécution nocturne plus petite et plus lente.
Exécuter la suite à chaque modification en CI
Une suite de régression qui réside sur votre ordinateur portable ne protège que votre ordinateur portable. L'objectif est de l'exécuter en intégration continue, sur les mêmes événements qui peuvent introduire une régression : les demandes de tirage (pull requests) et les fusions vers votre branche principale.
Le modèle est le même pour tous les systèmes de CI. Installez un exécuteur sans interface graphique (headless runner), dirigez-le vers votre suite enregistrée et faites échouer la construction si une assertion échoue. Apidog fournit un exécuteur en ligne de commande spécifiquement pour cela. Installez-le avec Node :
npm install -g apidog-cli
Ensuite, exécutez un scénario de test ou une suite enregistrée par son ID, contre un environnement choisi, et émettez des rapports :
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t 123456 \
-e 789012 \
-r cli,html,junit
Détaillons cela :
--access-tokenauthentifie l'exécution. Stockez le jeton en tant que secret CI, jamais dans le dépôt.-test l'ID du scénario, du dossier ou de la suite à exécuter.-eest l'ID de l'environnement, de sorte que la même suite peut cibler la staging ou la production en modifiant une valeur.-rliste les formats de rapport.cliimprime à la console,htmlproduit un rapport lisible, etjunitémet un XML que votre CI peut analyser pour afficher le succès/échec par test.
L'exécuteur est sans interface graphique (headless). Il s'adapte à toute étape de CI pouvant exécuter Node, de sorte que la même commande fonctionne dans GitHub Actions, GitLab CI, Jenkins ou CircleCI. Voici un job GitHub Actions qui exécute la suite à chaque demande de tirage :
name: API Regression
on: [pull_request]
jobs:
regression:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: '22'
- run: npm install -g apidog-cli
- run: |
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t 123456 \
-e 789012 \
-r cli,junit
env:
APIDOG_ACCESS_TOKEN: ${{ secrets.APIDOG_ACCESS_TOKEN }}
Lorsqu'un scénario échoue, l'exécuteur quitte avec un code non nul et le job passe au rouge. La demande de tirage est bloquée jusqu'à ce que quelqu'un y jette un œil. Pour un pipeline complet prêt à copier-coller et plus de modèles de CI, consultez Apidog CLI pour CI/CD et comment automatiser les tests d'API dans GitHub Actions.
Si vous alimentez la suite avec un fichier de données, passez-le avec `-d` :
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t 123456 \
-e 789012 \
-d ./test-data/emails.csv \
-r cli,junit
Vous testez une branche de fonctionnalité qui a sa propre version d'API ? Ajoutez `--branch` pour l'exécuter contre la suite enregistrée de cette branche au lieu de la suite par défaut. Pour conserver un historique des exécutions dans le cloud, ajoutez simplement le flag `--upload-report`.
Différenciation de schéma et de contrat
Les assertions détectent les régressions de comportement. La différenciation de schéma les détecte dans la définition, souvent avant le déploiement.
L'idée : votre spécification OpenAPI est un fichier versionné dans votre dépôt. Lorsque quelqu'un le modifie, vous comparez la nouvelle spécification à la précédente et classifiez le changement. Ajouter un champ facultatif est sûr. Supprimer un champ, en renommer un, restreindre un type ou rendre un champ facultatif obligatoire est un changement cassant. Un outil de différenciation peut signaler les changements cassants dans la demande de tirage, de sorte que le réviseur voit « cela supprime user.phone » au lieu d'un mur de YAML.
Associez cela à des tests de contrat sur l'API en direct. À chaque exécution, validez les réponses réelles par rapport au schéma actuel. Si la spécification promet un champ que l'API ne renvoie plus, ou si l'API renvoie un type que la spécification interdit, la vérification échoue. C'est la garde à double sens : la différenciation de spécification détecte les modifications intentionnelles du contrat, et le test de contrat détecte le code s'éloignant du contrat.
Les changements cassants ne sont pas toujours des bugs. Parfois, vous avez l'intention de supprimer un champ. L'intérêt de la différenciation est de rendre cette décision explicite et de l'acheminer via votre processus de versioning et de dépréciation au lieu de surprendre un client. Voir comment versionner et déprécier les API à grande échelle pour gérer les changements que vous faites délibérément.
Comment Apidog exécute les suites de régression
Apidog couvre les éléments décrits ci-dessus en un seul endroit, ce qui maintient la suite et la spécification côte à côte.
Vous construisez des scénarios de test visuellement : chaînez les requêtes, extrayez les valeurs d'une réponse pour les insérer dans la suivante, et attachez des assertions sur le statut, le schéma et les valeurs des champs. Étant donné que la conception de l'API et les tests vivent dans le même projet, vous pouvez valider les réponses par rapport au schéma enregistré du point de terminaison sans avoir à écrire le schéma deux fois. Lorsque la conception change, le schéma par rapport auquel les tests sont vérifiés change également.
Pour les cas basés sur les données, attachez un jeu de données CSV ou JSON à un scénario et Apidog exécute un cas par ligne. Enregistrez les scénarios connexes dans une suite de tests afin qu'une seule exécution exerce une ressource ou un flux entier.
L'exécuteur apidog-cli intègre ces suites enregistrées sans interface graphique (headless) dans la CI, comme illustré ci-dessus. Il exécute les scénarios et suites enregistrés. Ce n'est pas un émetteur de requêtes interactif ni un générateur de charge. Il a un seul objectif : rejouer votre suite de régression et rapporter ce qui a réussi. Cette portée étroite est ce qui lui permet de s'insérer dans n'importe quelle étape de CI compatible avec Node. Pour la CLI et un workflow scripté, consultez le guide du pipeline CI/CD d'Apidog CLI.
Un workflow de démarrage
Voici une séquence que vous pouvez adopter cette semaine sans reconstruire votre stratégie de test :
- Choisissez vos cinq points de terminaison les plus appelés. Le risque de régression se concentre là où le trafic est important. Commencez par là.
- Enregistrez une requête par point de terminaison avec des assertions. Code de statut, schéma de réponse et deux ou trois champs clés chacun. C'est votre référence.
- Ajoutez un flux enchaîné. Créer, lire, mettre à jour, supprimer sur votre ressource principale. Cela détecte les régressions inter-requêtes que les tests isolés manquent.
- Ajoutez une table de données à un point de terminaison à forte validation. Une poignée d'entrées valides, vides et incorrectes.
- Intégrez-le à la CI sur les demandes de tirage (pull requests). Installez
apidog-cli, exécutez la suite avec-r junitet bloquez les fusions en cas d'échec. - Développez la suite lorsqu'un bug s'échappe. Chaque régression de production qui passe inaperçue devient un nouveau cas de test. La suite se renforce de ses propres manquements.
Les étapes un à quatre prennent un après-midi. L'étape cinq est un seul fichier CI. Après cela, la suite s'exécute d'elle-même et vous ne l'étendez que lorsque la réalité vous apprend un nouveau mode de défaillance. Cette boucle de rétroaction est tout l'intérêt : un renommage qui aurait été un incident devient un point rouge sur une demande de tirage.
FAQ
En quoi le test de régression d'API diffère-t-il du test de régression général ? Le test de régression général revérifie le comportement de l'application sur l'ensemble du système, y compris l'interface utilisateur et la logique métier. Le test de régression d'API se concentre sur la surface HTTP : routes, codes de statut, schéma de réponse et valeurs des champs clés. Cette focalisation étroite le rend suffisamment rapide pour être exécuté à chaque commit, et il cible précisément ce à quoi d'autres systèmes se couplent.
À quelle fréquence dois-je exécuter la suite de régression ? À chaque modification susceptible d'affecter l'API. En pratique, cela signifie à chaque demande de tirage (pull request) et à chaque fusion vers votre branche principale, exécutée automatiquement en CI. Maintenez une suite de base rapide pour les demandes de tirage et une exécution de bout en bout plus vaste pour les builds nocturnes afin que la vérification par commit reste rapide.
Sur quoi dois-je faire des assertions pour éviter une suite fragile ? Faites des assertions sur ce qui ferait échouer un consommateur. Fixez les codes de statut, la structure et les types de réponse, ainsi que les valeurs des champs ayant une signification contractuelle, comme les identifiants et les énumérations de statut. Pour les valeurs qui changent à chaque requête, telles que les horodatages, faites des assertions sur le type et le format, et non sur la valeur littérale. Sur-assertir sur des données volatiles est la principale cause de faux échecs.
Puis-je exécuter des tests de régression d'API sans écrire de code ? Oui. Des outils comme Apidog vous permettent de construire des scénarios et des assertions visuellement, puis de les exécuter sans interface graphique (headless) en CI avec apidog-cli. Vous enregistrez la suite une fois via l'interface et l'exécuteur en ligne de commande la rejoue dans votre pipeline, de sorte que les tests s'exécutent automatiquement sans un harnais de test écrit à la main.
Comment gérer les changements cassants intentionnels ? Acheminez-les via votre processus de versioning et de dépréciation plutôt que de les laisser apparaître comme des échecs de test surprenants. Utilisez la différenciation de schéma pour signaler le changement lors de la revue, versionnez le point de terminaison ou ajoutez le champ comme facultatif en premier, et mettez à jour délibérément la référence de régression une fois que le changement est voulu et communiqué aux consommateurs.
