Tests négatifs des API

Comprendre les tests négatifs des API et les catégories de requêtes invalides à vérifier régulièrement.

Mis à jour:

Sommaire

Les tests positifs montrent qu’une API traite les scénarios attendus. Les tests négatifs évaluent sa résistance aux entrées invalides, inattendues ou dangereuses. Ils sont particulièrement utiles en QA, car ils révèlent souvent des faiblesses de validation, de gestion des erreurs, de sécurité et de stabilité du service.

Les utilisateurs et les intégrations ne se comportent pas toujours parfaitement. Ils peuvent envoyer des champs vides, des types incorrects, des jetons expirés, des corps trop volumineux ou appeler des endpoints dans un état invalide. Une bonne API doit répondre de façon prévisible et sûre, au-delà de la simple absence de plantage.

Que signifie tester négativement une API ?

Les tests négatifs examinent le comportement du système face à des entrées invalides, inattendues, interdites ou contradictoires.

Ils couvrent bien plus que l’envoi d’un champ vide :

  • →Champs obligatoires absents
  • →Valeurs mal formatées
  • →Types de données incompatibles
  • →Valeurs hors limites
  • →Combinaisons de champs qui violent les règles métier
  • →Utilisateurs non authentifiés ou non autorisés
  • →Corps de requête trop volumineux
  • →Content-Type inattendu
  • →Méthodes qui ne devraient pas être acceptées par cet endpoint
  • →Requêtes répétées qui créent des conflits

Les tests négatifs vérifient donc la validité des entrées et la résistance de l’API aux usages incorrects.

Pourquoi est-ce particulièrement important pour les API ?

Une UI offre une certaine protection grâce aux formulaires, masques, listes déroulantes et boutons désactivés. Les API ne disposent pas de cette couche : elles reçoivent des requêtes brutes et doivent décider comment les traiter.

Des tests négatifs insuffisants laissent généralement trois risques :

  • →Le service échoue sur une entrée incorrecte.
  • →Le service se comporte de façon imprévisible.
  • →Le service accepte une entrée qu’il devrait refuser.

Tester uniquement le parcours nominal révèle une très petite partie du comportement réel du système.

Que faut-il mettre à l’épreuve ?

De bons tests négatifs suivent des classes d’entrées plutôt que des tentatives arbitraires de saisie incohérente.

Testez régulièrement ces catégories :

  • →Un champ obligatoire est absent.
  • →Un champ est présent mais vide.
  • →Un champ est présent mais vaut null.
  • →Le type est incorrect : chaîne au lieu d’un nombre, ou objet au lieu d’un tableau.
  • →Une chaîne dépasse la longueur maximale.
  • →Un nombre est inférieur au minimum ou supérieur au maximum.
  • →Une date, une adresse e-mail, un téléphone, un UUID ou une valeur énumérée possède un format invalide.
  • →Les paramètres forment une combinaison invalide.
  • →Des champs supplémentaires inattendus sont présents.
  • →La méthode de la requête est incorrecte.
  • →Le Content-Type est incorrect.
  • →Le jeton est corrompu ou expiré.
  • →La requête vise une ressource d’un autre utilisateur.
  • →Le corps de la requête est trop volumineux.
  • →La requête est répétée dans un état incompatible.

Une approche systématique transforme ces vérifications en modèle reproductible de qualité de l’API, au lieu de tentatives désordonnées pour provoquer une panne.

Ce qui fait un bon test négatif

Un test négatif faible vérifie seulement qu’une erreur s’est produite. Un test solide examine bien davantage.

  • →Le code de statut est-il correct ?
  • →L’erreur est-elle compréhensible pour le client ?
  • →La réponse expose-t-elle des détails internes inutiles ?
  • →Des données ont-elles changé alors qu’elles auraient dû rester intactes ?
  • →Y a-t-il eu des effets de bord ?
  • →Répéter la même requête invalide produit-il un comportement cohérent ?
  • →Le service évite-t-il de renvoyer 500 pour un problème imputable au client ?

Par exemple, du JSON invalide justifie généralement 400 plutôt que 500. Une tentative de modification de la ressource d’un autre utilisateur appelle habituellement 403 ou 404, pas un succès. Un corps trop volumineux peut justifier 413. L’objectif est une gestion cohérente et compréhensible, pas la recherche d’un code idéal universel.

Que vérifier au-delà de l’erreur ?

Une bonne habitude consiste à toujours vérifier l’état du système après une requête échouée.

  • →Aucun enregistrement n’a-t-il réellement été créé ?
  • →Le statut de l’objet est-il resté inchangé ?
  • →Aucune somme n’a-t-elle été débitée ?
  • →Aucun e-mail n’a-t-il été envoyé ?
  • →L’audit et les journaux ont-ils correctement enregistré l’événement ?
  • →La répétition de la requête a-t-elle laissé le système dans un état valide ?

De nombreux défauts dangereux se cachent ici : l’API renvoie une erreur, mais a déjà partiellement modifié les données. L’utilisateur peut découvrir plus tard un bug apparemment aléatoire, alors que sa cause est une mauvaise gestion des scénarios négatifs.

Exemple pratique

Prenons un endpoint de création d’utilisateur.

Le scénario positif est simple : envoyer une adresse e-mail, un nom et un mot de passe valides, puis recevoir 201 Created.

Examinons maintenant les scénarios négatifs :

  • →L’adresse e-mail est absente.
  • →L’adresse e-mail est vide.
  • →L’adresse e-mail est invalide.
  • →Le mot de passe est trop court.
  • →Un champ du corps possède un type inattendu.
  • →L’autorisation requise est absente.
  • →La même adresse e-mail est enregistrée de nouveau.
  • →Le corps est trop volumineux.
  • →Le Content-Type n’est pas application/json.

L’équipe QA doit vérifier que :

  • →Le serveur répond de façon prévisible.
  • →L’erreur est suffisamment claire pour le client.
  • →Le code de statut correspond à la catégorie du problème.
  • →Aucun enregistrement invalide n’est créé.
  • →Aucun effet de bord indésirable ne se produit.
  • →Répéter la même requête invalide ne dégrade pas davantage le système.

Les tests négatifs deviennent alors une véritable évaluation de la maturité de l’API, au-delà d’un supplément facultatif.

Points essentiels pour les ingénieurs QA

  • →Les tests négatifs des API évaluent leur résistance autant que les erreurs de saisie.
  • →Un bon test négatif vérifie le code d’erreur et l’état du système après la requête.
  • →Une API solide traite les mauvaises requêtes de façon sûre et prévisible.
  • →Le parcours nominal seul démontre rarement la fiabilité réelle du service.
  • →Organisez les tests négatifs par catégories de risques plutôt que par tentatives aléatoires de panne.

Lectures complémentaires

  • →Dans cette base de connaissances : méthodes, codes de statut et en-têtes
  • →Dans cette base de connaissances : authentification et autorisation
  • →Ressource externe : Aide-mémoire OWASP sur la sécurité REST

Une matrice locale de tests négatifs avec vérification des effets de bord

Utilisez un contrat local synthétique au lieu de deviner ce que toutes les API devraient renvoyer. L’environnement pédagogique accepte POST /items avec un jeton administrateur de formation, le Content-Type application/json, un nom de 3 à 12 lettres ASCII et une quantité entière de 1 à 5. Le corps doit contenir exactement ces deux champs. Les données restent en mémoire ; démarrez un nouveau serveur pour chaque test indépendant.

plain text
Cas	Exemple	Résultat attendu dans cet environnement de test
Champ absent	{"name":"abc"}	422 invalid_fields
Type incorrect	{"name":"abc","quantity":"1"}	422 invalid_quantity
Valeur hors limites	{"name":"abc","quantity":6}	422 invalid_quantity
Champ supplémentaire	{"name":"abc","quantity":1,"admin":true}	422 invalid_fields
JSON mal formé	{	400 malformed_json
Type de contenu incorrect	Content-Type: text/plain	415 json_required
Corps de plus de 1024 octets	Corps de 1025 octets	413 payload_too_large

Avant chaque écriture refusée, appelez GET /items et relevez total ; répétez après et exigez une valeur inchangée. Cela détecte une implémentation qui renvoie une erreur après avoir enregistré des données. Pour un nouveau nom accepté, attendez 201 et total + 1 ; un nouvel envoi du même nom renvoie 409 sans ajout supplémentaire. Ces statuts décrivent le contrat déclaré, pas une règle obligatoire pour tous les produits.

plain text
python3 mock_api.py --port 8765
# In another terminal, using only the synthetic local token:
curl -i http://127.0.0.1:8765/items -H "Authorization: Bearer demo-admin" -H "Content-Type: application/json" --data '{"name":"abc","quantity":6}'
python3 -m unittest test_mock_api.py -v

Cet environnement de test est volontairement local et simplifié. Il sert à choisir les entrées et à recueillir des preuves ; ne reprenez pas ses jetons fixes ni son serveur HTTP dans un système d’authentification de production.

Pour aller plus loin

Télécharger le laboratoire local de pratique (ZIP)

Vérifier séparément les autorisations

Déterminer les valeurs limites