Aller au contenu
English

Tests et exécutions reproductibles

  • Leçon 15
  • 50 min
  • Module 5 : Explorer et tester avec Postman

Ce que vous saurez faire

Transformez la collection en une vérification que tout le monde peut exécuter avec une seule commande. Elle vérifie chaque requête, chaque code d’état attendu et chaque champ, en moins d’une seconde. Vous réutiliserez cette vérification au module 7 pour prouver que l’API déployée fonctionne.

Avant de commencerCe qu’il faut savoir et avoir sous la mainEnviron 50 minutes

Ce que vous devez savoir

Ce qu’il vous faut sur votre ordinateur

Testé avec Postman CLI 1.69.0 sur macOS. Les étapes dans l’application suivent la documentation de Postman pour Postman 12.

Jusqu’ici, vous lisiez chaque réponse pour décider si elle était correcte. Un test dans Postman est un court script JavaScript qui s’exécute après l’arrivée de la réponse et la vérifie. Vous l’écrivez dans l’onglet Scripts (scripts) de la requête, sous Post-response (après la réponse) :

Post-response script of Classify a support ticket
pm.test("status is 200", () => pm.response.to.have.status(200));
const result = pm.response.json();
pm.test("category is billing", () => pm.expect(result.category).to.equal("billing"));
pm.test("priority is 1 to 3", () => pm.expect(result.priority).to.be.within(1, 3));
pm.test("answers in under 500 ms", () => pm.expect(pm.response.responseTime).to.be.below(500));
Partie Signification
pm.test("name", () => ...) Un test dont le nom indique ce qu’il vérifie. Il réussit si le code à l’intérieur ne produit aucun échec.
pm.response.to.have.status(200) Le code d’état doit être 200.
pm.response.json() Le corps de la réponse, lu comme du JSON.
pm.expect(value).to.equal(...) La valeur doit être égale à celle indiquée. Aussi : .to.be.within(1, 3), .to.include(...), .to.be.below(...), .to.include.all.keys(...).
pm.response.responseTime Le temps pris par la réponse, en millisecondes.

Vous n’avez pas besoin de connaître JavaScript pour cela. Les mêmes quelques lignes, avec différentes valeurs, couvrent presque tous les tests de ce cours. Après l’envoi, l’onglet Test Results (résultats des tests) du volet de réponse indique si chaque test réussit ou échoue.

Certaines vérifications sont les mêmes pour chaque requête : dans cette API, chaque réponse est en JSON. Chaque erreur a aussi la structure du module 3. Écrivez ces vérifications une seule fois, dans le script Post-response de la collection. Postman l’exécute après chaque requête de la collection :

Post-response script of the collection
pm.test("response is JSON", () => pm.response.to.be.json);
if (pm.response.code >= 400) {
pm.test("error has the standard shape", () => {
const error = pm.response.json().error;
pm.expect(error).to.include.all.keys("code", "message", "fields");
});
}

to.include.all.keys signifie « contient au moins ces clés ». Une vérification plus stricte, to.have.keys, signifie « contient exactement ces clés ». Elle échouerait dès que l’API ajoute un champ à ses erreurs, même si cet ajout ne brise pas la compatibilité. Vérifiez ce dont les clients dépendent, et permettez ce que le contrat permet.

Chaque requête vérifie ensuite seulement ce qui lui est propre. Voici les tests pour les requêtes d’échec :

Reject an empty subject
pm.test("status is 422", () => pm.response.to.have.status(422));
const error = pm.response.json().error;
pm.test("code is invalid_request", () => pm.expect(error.code).to.equal("invalid_request"));
pm.test("names the subject field", () => pm.expect(error.fields).to.include("subject"));
Reject an unknown field
pm.test("status is 422", () => pm.response.to.have.status(422));
pm.test("names the colour field", () => pm.expect(pm.response.json().error.fields).to.include("colour"));
Reject a GET on classify
pm.test("status is 405", () => pm.response.to.have.status(405));
pm.test("code is method_not_allowed", () => pm.expect(pm.response.json().error.code).to.equal("method_not_allowed"));

Collection Runner (outil d’exécution des collections) envoie chaque requête de la collection, dans l’ordre, et affiche chaque résultat de test :

  1. Sélectionnez la collection dans la barre latérale, puis l’icône Run (exécuter).
  2. Sous Run type (type d’exécution), choisissez Functional (fonctionnel), puis Local.
  3. Choisissez l’environnement Postman Local.
  4. Sélectionnez Start run (démarrer l’exécution).

L’exécution affiche chaque requête avec son code d’état et ses tests. Toute la collection s’exécute en moins d’une seconde. Vous pouvez donc l’exécuter après chaque modification de l’API.

La collection se trouve dans votre compte Postman. Intégrez la vérification au projet pour qu’elle soit révisée avec le code et puisse s’exécuter sur n’importe quel ordinateur. Pour cela, exportez-la dans le projet :

  1. Dans la barre latérale, à côté de la collection, sélectionnez View more actions (voir d’autres actions), les …. Sélectionnez ensuite More › Export collection (plus › exporter la collection), puis Export JSON (exporter en JSON).
  2. Enregistrez le fichier dans un nouveau dossier postman du projet, sous le nom ticket-api.postman_collection.json.
  3. Dans Environments (environnements), à côté de Local, sélectionnez View more actions, puis Export (exporter). Enregistrez le fichier sous le nom postman/local.postman_environment.json.
  4. Ouvrez le fichier d’environnement dans VS Code et vérifiez que "value" (valeur) est vide pour apiKey. Si une vraie clé apparaît, supprimez-la du fichier et lisez l’erreur fréquente dans la leçon précédente.

Postman CLI exécute un fichier de collection depuis le terminal. Il n’a pas besoin d’un compte Postman pour exécuter un fichier de votre projet. Toute personne qui a votre projet peut donc exécuter vos vérifications.

  1. Installez Postman CLI :

    Fenêtre de terminal
    curl -o- "https://dl-cli.pstmn.io/install/unix.sh" | sh

    Si vous avez Node.js, npm install -g postman-cli fonctionne aussi.

  2. Ouvrez un nouveau terminal pour qu’il trouve la nouvelle commande. Vérifiez-la : postman --version. La sortie est un numéro de version, comme 1.69.0.

  3. Dans le dossier du projet, avec l’API en marche, exécutez la collection avec l’environnement Local :

    Fenêtre de terminal
    postman collection run postman/ticket-api.postman_collection.json -e postman/local.postman_environment.json
Output (start and end)
No authorization data found. Please use the `postman login` command.
Running your collection...
Ticket Classifier API
Folder tickets
Sub-folder List the ticket categories
GET http://127.0.0.1:8000/v1/categories [200 OK, 202 B, 8 ms]
Pass response is JSON
Pass status is 200
Pass lists 5 categories
...
| requests | 6 | 0 |
| assertions | 24 | 0 |

La première ligne indique seulement que vous n’êtes pas connecté. L’outil en ligne de commande exécute quand même le fichier local. Six requêtes et 24 vérifications, toutes réussies. Le code de sortie est 0.

Pour exécuter un seul dossier, ajoutez -i avec son nom : -i health exécute seulement Check that the service runs (vérifier que le service fonctionne).

Arrêtez l’API (Ctrl+C dans son terminal), puis exécutez de nouveau la collection :

Sortie (abrégée)
GET http://127.0.0.1:8000/v1/categories [errored]
connect ECONNREFUSED 127.0.0.1:8000
...
# failure detail
01. Error connect ECONNREFUSED 127.0.0.1:8000
inside "tickets / List the ticket categories"
02. AssertionError response is JSON
...
| requests | 6 | 6 |

Chaque requête échoue, et le code de sortie est 1. C’est ce qu’une vérification doit faire : signaler clairement l’échec avec un code de sortie non nul. Ainsi, un script ou une tâche automatique s’arrête. Le premier échec (ECONNREFUSED, connexion refusée) vous indique pourquoi : l’étape de connexion, présentée au module 1. Redémarrez l’API.

Les deux testent l’API. Ils la testent depuis des endroits différents. Un bon projet utilise donc les deux :

Collection Postman pytest (module 6)
Envoie de vraies requêtes HTTP à Une API en marche, locale ou déployée L’application en mémoire, sans serveur
Voit Seulement les requêtes et les réponses, comme un client Aussi l’intérieur : remplacer le classificateur, modifier les paramètres
Idéal pour Explorer, fournir des exemples aux autres développeurs, vérifier une API déployée Vérifier chaque règle et chaque chemin d’échec, rapidement, à chaque modification
Peut tester « le classificateur est en panne »? Seulement si l’API déployée est vraiment en panne Oui, en donnant à la route un classificateur qui ne fonctionne pas

Utilisez pytest pour les tests détaillés du code. Utilisez la collection pour vérifier le contrat de l’extérieur, surtout pour vérifier un déploiement, auquel pytest n’a pas accès.

  1. Ajoutez le script de la collection et les tests de chaque requête des exemples détaillés. Ajoutez vos propres tests pour List the ticket categories (lister les catégories de billets de soutien) : état 200, cinq catégories. Faites de même pour Check that the service runs : état 200, "status": "ok".
  2. Envoyez chaque requête et lisez son onglet Test Results.
  3. Exécutez toute la collection dans Collection Runner avec Local. Chaque test réussit.
  4. Exportez la collection et l’environnement Local dans postman/. Vérifiez que le fichier d’environnement ne contient aucune clé.
  5. Installez Postman CLI et exécutez la collection depuis le terminal. Vérifiez le résumé et le code de sortie (echo $?, ou $LASTEXITCODE dans PowerShell).
  6. Arrêtez l’API et exécutez de nouveau la collection. Le code de sortie est 1. Redémarrez l’API.

À vous de jouer : briser le contrat et voir qui le remarque

Section intitulée « À vous de jouer : briser le contrat et voir qui le remarque »

Dans models.py, changez la limite de subject de max_length=120 à max_length=10, puis enregistrez. Exécutez ensuite, dans cet ordre :

  1. La collection Postman depuis le terminal.
  2. python -m pytest.

Quelles vérifications échouent? Quelle vérification échouerait si vous aviez plutôt changé la limite à 200? Annulez la modification après l’exercice.

Afficher la réponse

Avec 10, la collection échoue sur Classify a support ticket (classer un billet de soutien). "Charged twice for March" (facturé deux fois pour mars) dépasse 10 caractères, donc l’API répond 422. Le test de contrat pytest du module 4 échoue aussi, car maxLength a changé dans le document OpenAPI. Le test de l’exemple échoue également.

Avec 200, tous les tests Postman réussissent : aucune requête de la collection n’envoie un objet de plus de 120 caractères. Seul le test de contrat pytest remarque que la limite documentée a changé. Voilà pourquoi vous avez besoin des deux : la collection vérifie le comportement de l’extérieur, et le test de contrat vérifie l’engagement. Pour que la collection le remarque aussi, ajoutez une requête qui envoie exactement 121 caractères et attend 422.

Erreur courante

Chaque requête produit une erreur dans le terminal, mais fonctionne dans l'application

Symptôme : l’exécution dans le terminal marque chaque requête [errored] (en erreur), avec l’un des messages suivants. Pourtant, la même collection fonctionne dans l’application :

GET {{baseUrl}}/v1/categories [errored]
getaddrinfo ENOTFOUND {{baseurl}}
GET //v1/categories [errored]
Invalid URI "http:////v1/categories"

Cause : l’exécution n’a aucune valeur utilisable pour baseUrl. Dans le premier cas, rien n’a remplacé {{baseUrl}} : la commande n’a pas d’option -e ou pointe vers le mauvais fichier. Dans le second cas, l’exécution a utilisé la variable de collection baseUrl = / provenant de l’importation. Le fichier d’environnement ne contient aucune variable portant exactement ce nom. Les noms de variables distinguent les majuscules des minuscules : baseURL n’est pas baseUrl.

Solution :

  1. Vérifiez la commande : -e postman/local.postman_environment.json, avec le bon chemin.
  2. Ouvrez le fichier d’environnement et vérifiez le nom exact baseUrl et sa valeur.
  3. Pour une vérification rapide, définissez la valeur dans la commande : --env-var "baseUrl=http://127.0.0.1:8000".

Vérifiez votre compréhension

Pourquoi le script de la collection vérifie-t-il la structure d'erreur seulement quand le code d'état est de 400 ou plus?

Afficher la réponse

Seules les réponses d’erreur ont la structure error. Une réponse 200 de /v1/classify contient category, priority, etc. La vérification échouerait donc pour chaque réussite. La condition permet au même script de vérifier correctement chaque requête de la collection. Toutes les réponses doivent être en JSON, et toutes les erreurs doivent contenir code, message et fields.

Vérifiez votre compréhension

Vérification du module : la collection s'exécute depuis le terminal et tous les tests réussissent. Vous arrêtez ensuite l'API. Qu'affiche l'exécution, quel est son code de sortie et pourquoi ce code est-il important?

Afficher la réponse

Chaque requête est marquée [errored] avec connect ECONNREFUSED 127.0.0.1:8000. Les tests qui suivent échouent, et le code de sortie est 1. Le code de sortie compte parce que les programmes le lisent, pas les personnes. Un script ou une vérification automatique du déploiement s’arrête sur un code de sortie non nul. Une vérification qui afficherait des erreurs mais retournerait 0 laisserait passer un déploiement défectueux.

Récapitulatif

  • Un test Postman est un pm.test dans le script Post-response d’une requête. Test Results affiche le résultat.
  • Les vérifications communes à toutes les requêtes vont dans le script de la collection, une seule fois.
  • Collection Runner exécute chaque requête et chaque test avec l’environnement Postman choisi.
  • Exportez la collection et l’environnement, sans secrets, dans le dossier postman du projet.
  • postman collection run <file> -e <environment> les exécute depuis le terminal, sans connexion, et retourne 1 si quelque chose échoue.
  • Utilisez la collection pour vérifier l’API de l’extérieur, et pytest pour tester le code en détail.

Vous pouvez maintenant explorer, documenter et vérifier l’API avec Postman. Dans le prochain module, vous rendrez l’API robuste : tests automatisés pour chaque chemin, journaux (logs) utiles et protection.

Leçon suivante : Tests automatisés des points de terminaison