Écrire un test par propriété
Exercice supplémentaire · niveau 3 (difficile) · NSI (première), chapitre 3 — Langages et programmation · Tester autrement : doctest, assertions, mesures
Énoncé
Écrire un test par propriété : au lieu de choisir les cas, les tirer au hasard. Vérifier sur couples aléatoires la propriété d'inversion du chapitre 1. Quels sont les deux dangers de cette manière de tester, et comment y remédier ?
Corrigé
import random
random.seed(2026) # <-- la ligne qui rend l'echec reproductible
for _ in range(10000):
n = random.randint(0, 10**6)
b = random.randint(2, 16)
assert depuis_base(vers_base(n, b), b) == n
Les tirages passent.
Premier danger : l'irreproductibilité. Sans random.seed, un échec survenu une fois peut ne jamais se reproduire — on sait qu'un défaut existe, on ne sait plus sur quelle entrée. Fixer la graine rend la suite de tirages identique d'une exécution à l'autre : c'est ce qui transforme un incident en un cas de test. Il faut aussi afficher l'entrée fautive quand l'assertion tombe.
Second danger : la loi de tirage ignore les cas limites. Tirer uniformément entre et ne produit presque jamais , ni , ni une puissance de deux exacte — or c'est là que se trouvent les erreurs. Un tirage uniforme explore le milieu du domaine et néglige ses bords. Le remède est de mélanger les deux :
cas_limites = [0, 1, 2, 15, 16, 255, 256, 10**6]
for n in cas_limites:
for b in range(2, 17):
assert depuis_base(vers_base(n, b), b) == n
Hors programme mais très employé : les bibliothèques de property-based testing (Hypothesis en Python, QuickCheck à l'origine) automatisent tout cela — elles tirent, elles gardent la graine, et surtout elles réduisent un contre-exemple trouvé jusqu'au plus petit qui échoue encore.
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.