Tests par paires

Réduire les combinaisons de paramètres grâce aux tests par paires : avantages, limites et choix d’une couverture utile.

Mis à jour:

Sommaire

De nombreux paramètres et valeurs rendent coûteux les tests combinés exhaustifs. Les tests par paires réduisent le nombre de tests tout en couvrant chaque paire de valeurs de paramètres. Il équilibre souvent le coût des tests avec la probabilité de détecter des défauts.

Pourquoi les tests par paires sont utiles

De nombreux défauts résultent d’interactions entre deux facteurs plutôt que de rares combinaisons de cinq ou six. Couvrir chaque paire permet donc de détecter une part substantielle de problèmes avec beaucoup moins de tests.

Où l'appliquer

  • →Formulaires avec plusieurs champs et valeurs indépendants.
  • →Combinaisons d'appareils, de navigateurs, de rôles, de forfaits, de pays et de langues.
  • →API avec de nombreux paramètres et modes d'appel.
  • →Matrices de compatibilité où les tests exhaustifs sont trop coûteux.

Ce qu'il faut retenir

  • →Les tests par paires ne remplacent ni les vérifications de risques métier critiques ni les combinaisons dangereuses connues.
  • →Les paramètres dépendants ne doivent pas être mélangés aveuglément avec des paramètres indépendants.
  • →Excluez à l’avance les combinaisons logiquement impossibles.
  • →Ajoutez des scénarios critiques à côté de l’ensemble généré par paires.

Conseils pratiques

Utilisez les tests par paires pour optimiser la couverture, pas pour justifier une suite minimale à tout prix. Identifiez manuellement les cas à haut risque, complétez-les par une couverture par paires, puis renforcez l’ensemble avec des scénarios négatifs et des valeurs limites.

🧩

Pairwise aide lorsque les combinaisons de paramètres constituent le véritable problème. Ce n'est pas une solution universelle pour les séquences, états ou calculs complexes.

Exemple concret : quatre tests couvrant les douze paires

Ce modèle fictif comprend trois facteurs : navigateur (Chrome ou Firefox), langue de l’interface (ru ou en) et rôle du compte (viewer ou editor). Les huit combinaisons sont autorisées. Les versions de navigateur, l’OS, le jeu de données et les fonctionnalités activées restent fixes pendant l’exercice ; relevez leurs valeurs exactes lors d’un vrai test navigateur. Ce modèle sélectionne les entrées ; ce n’est pas une application web exécutable.

La couverture de toutes les combinaisons exige 2 × 2 × 2 = 8 lignes. La couverture par paires vise chaque paire de valeurs de facteurs différents : quatre paires navigateur-langue, quatre navigateur-rôle et quatre langue-rôle. Les quatre lignes suivantes couvrent ces douze paires.

plain text
ID	Navigateur	Langue	Rôle
PW1	Chrome	ru	viewer
PW2	Chrome	en	editor
PW3	Firefox	ru	editor
PW4	Firefox	en	viewer

Auditez la couverture plutôt que de faire confiance au nombre de lignes

plain text
Facteur A	Facteur B	Couvert par
Navigateur=Chrome	Langue=ru	PW1
Navigateur=Chrome	Langue=en	PW2
Navigateur=Firefox	Langue=ru	PW3
Navigateur=Firefox	Langue=en	PW4
Navigateur=Chrome	Rôle=viewer	PW1
Navigateur=Chrome	Rôle=editor	PW2
Navigateur=Firefox	Rôle=viewer	PW4
Navigateur=Firefox	Rôle=editor	PW3
Langue=ru	Rôle=viewer	PW1
Langue=ru	Rôle=editor	PW3
Langue=en	Rôle=viewer	PW4
Langue=en	Rôle=editor	PW2

Chaque ligne du tableau nomme une paire requise et le test la contenant. Le tableau couvre chaque paire une fois. Quatre tests sont minimes pour ce modèle binaire sans contrainte : les quatre paires navigateur-paramètres régionaux nécessitent à elles seules au moins quatre lignes. Cette conclusion s’applique uniquement à ce modèle spécifique, et non aux suites arbitraires par paires.

Vérifiez la matrice avec Python 3

Copiez ce code dans pairwise_coverage.py et exécutez python3 pairwise_coverage.py. Il utilise uniquement la bibliothèque standard et n’envoie aucune requête réseau. Sortie attendue : Pairs: 12/12; triples: 4/8.

plain text
from itertools import product, combinations
levels = [("Chrome", "Firefox"), ("ru", "en"), ("viewer", "editor")]
rows = [
    ("Chrome", "ru", "viewer"),
    ("Chrome", "en", "editor"),
    ("Firefox", "ru", "editor"),
    ("Firefox", "en", "viewer"),
]
required = {(i, a, j, b) for i, j in combinations(range(3), 2)
            for a, b in product(levels[i], levels[j])}
covered = {(i, row[i], j, row[j]) for row in rows
           for i, j in combinations(range(3), 2)}
assert all(row in set(product(*levels)) for row in rows)
assert covered == required
assert ("Chrome", "en", "viewer") not in rows
print(f"Pairs: {len(covered)}/{len(required)}; triples: {len(set(rows))}/8")

Donnez à chaque configuration un oracle comportemental

Pour une fonction de document fictive, définissez la règle avant l’exécution : un viewer peut lire, mais une tentative de modification laisse le contenu enregistré inchangé ; un editor peut enregistrer une modification valide une seule fois. Pour chaque ligne, vérifiez la langue choisie, le résultat propre au rôle et les données enregistrées. La couverture des paires ne prouve pas ces résultats : une configuration déclarée réussie n’apporte aucune preuve sans assertions.

Un défaut déclenché uniquement par Chrome + en + viewer est manqué par cette matrice : ce triplet est absent même si toutes ses paires apparaissent ailleurs. Ajoutez cette combinaison lorsque le risque ou un défaut antérieur le justifie. Les contrôles de séquence, de limites, d'autorisation et de performances nécessitent toujours une conception distincte. Aucun pourcentage de défauts trouvés ne découle des « paires 12/12 ».

Si une contrainte rend une combinaison impossible, générez d’abord les combinaisons complètes autorisées, déduisez-en les paires réalisables, puis régénérez et vérifiez la suite réduite. Supprimer simplement une ligne invalide peut faire perdre des paires valides. Exercice : retirez PW4 ; Firefox–en, Firefox–viewer et en–viewer ne sont plus couverts. Restaurez une ligne de couverture valide plutôt que d’abaisser silencieusement le dénominateur.

Pour aller plus loin

Choisissez des cas supplémentaires par risque

Planifier des vérifications multi-navigateurs

NIST : tests combinatoires et couverture des interactions