Comment choisir les cas de test ?
Choisir des cas de test, c’est décider quelles valeurs essayer pour trouver le plus de fautes avec le moins de tests. On ne peut pas tout essayer : on regroupe les valeurs qui se comportent pareil, puis on teste surtout aux frontières.
Un musée vend ses billets selon l’âge. Entre 0 et 120 ans, il y a 121 âges possibles. Il suffit d’en essayer une dizaine bien choisis.
À la fin de cette leçon
Remarque
Je peux choisir des cas de test avec des classes d’équivalence et des valeurs limites.
Mots-clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Classe d’équivalence | un groupe de valeurs que le programme traite de la même façon | les âges de 6 à 17 ans |
| Représentant | une valeur choisie pour parler de toute sa classe | |
| Valeur limite | la première ou la dernière valeur d’une classe, et ses voisines | 17 et 18 |
| Cas invalide | une valeur que le programme doit refuser | un âge de -1 |
| Table de cas | un tableau qui liste chaque valeur essayée et le résultat attendu | |
| Erreur d’un cran | une faute où < est écrit à la place de <=, ou l’inverse |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
La règle de tarif du musée
Voici la règle, en centimes. Un enfant de moins de 6 ans entre gratuitement. De 6 à 17 ans, le billet coûte 400. De 18 à 64 ans, il coûte 900. À partir de 65 ans, il coûte 600.
Un âge négatif n’a pas de sens : le programme doit le refuser.
Une classe regroupe des valeurs qui se ressemblent
Un enfant de 8 ans et un enfant de 12 ans paient pareil, car la fonction suit le même chemin pour les deux. Si l’un marche, l’autre marche aussi.
On prend donc une valeur par classe, son représentant. Pour le musée, il y a cinq classes, dont une invalide.
Exemple travaillé : les classes du musée
| Classe | Âges | Représentant | Résultat attendu |
|---|---|---|---|
| Invalide | moins de 0 | -5 | une erreur |
| Enfant | 0 à 5 | 3 | 0 |
| Jeune | 6 à 17 | 12 | 400 |
| Adulte | 18 à 64 | 40 | 900 |
| Senior | 65 et plus | 80 | 600 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Les fautes se cachent aux frontières
Les programmeurs se trompent souvent d’un cran : ils écrivent < au lieu de <=. Le représentant d’une classe ne le voit pas.
Il faut donc tester les valeurs limites : la dernière valeur d’une classe, la première de la suivante, et les voisines. Pour les jeunes, ce sont 5, 6, 17 et 18.
Écrire la fonction du musée
printf 'def tarif_musee(age):\n if age < 0:\n raise ValueError("age negatif")\n if age < 6:\n return 0\n if age < 18:\n return 400\n if age < 65:\n return 900\n return 600\n' > essais/musee.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Essayer les valeurs limites
PYTHONPATH=essais python3 -c "from musee import tarif_musee; print([tarif_musee(a) for a in [5, 6, 17, 18, 64, 65]])"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Lire la liste des résultats
La commande affiche [0, 400, 400, 900, 900, 600]. Chaque nombre répond à l’âge de la même place : 5, 6, 17, 18, 64, 65.
Le prix change entre 5 et 6, entre 17 et 18, et entre 64 et 65. Les limites sont donc exactement là où les prix bondissent.
Écrire une version avec une erreur d’un cran
printf 'def tarif_musee(age):\n if age < 0:\n raise ValueError("age negatif")\n if age <= 6:\n return 0\n if age < 18:\n return 400\n if age < 65:\n return 900\n return 600\n' > essais/musee_faux.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Essayer les mêmes âges sur la version fautive
PYTHONPATH=essais python3 -c "from musee_faux import tarif_musee; print([tarif_musee(a) for a in [5, 6, 17, 18, 64, 65]])"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Un représentant ne voit pas l’erreur d’un cran
La version fautive affiche [0, 0, 400, 900, 900, 600]. À 6 ans, elle rend 0 au lieu de 400.
Les représentants 3, 12, 40 et 80 donnent tous le bon résultat sur les deux versions. Seul l’âge limite 6 montre la faute.
Une table de cas range tous les cas
Une table de cas liste chaque valeur essayée et le résultat attendu. On l’écrit une fois, puis une boucle la parcourt.
Chaque ligne est un cas : l’âge, puis le prix. Ajouter un cas, c’est ajouter une ligne.
Une boucle parcourt la table de cas
def tarif_musee(age):
if age < 6:
return 0
if age < 18:
return 400
if age < 65:
return 900
return 600
# Chaque cas : [age, prix attendu]. Les limites sont à 5, 6, 17, 18, 64 et 65.
CAS = [[3, 0], [5, 0], [6, 400], [12, 400], [17, 400],
[18, 900], [40, 900], [64, 900], [65, 600], [80, 600]]
for cas in CAS:
obtenu = tarif_musee(cas[0])
if obtenu != cas[1]:
print("Echec pour l'age", cas[0], ":", obtenu, "au lieu de", cas[1])
print("Table parcourue")
Erreur fréquente
Attention
Beaucoup pensent qu’il faut beaucoup de tests, ou des valeurs au hasard. Cent âges pris dans la même classe trouvent la même faute qu’un seul. Mieux vaut peu de cas bien choisis : un par classe, plus les frontières.
Lister les valeurs limites d’une liste de classes
Dans le devoir, une classe est une liste de deux nombres : son premier et son dernier âge. Par exemple [6, 17].
Pour chaque classe, vous gardez six valeurs : début moins un, début, début plus un, fin moins un, fin, fin plus un. Vous les rendez sans doublon, dans l’ordre croissant. Les classes voisines partagent des valeurs.