Pour l'un de ces modules, écrire le jeu de tests avant d'écrire le…
Exercice de TD · niveau 2 · NSI (première), chapitre 11 — Conduire un projet · Du sujet au découpage
Énoncé
Pour l'un de ces modules, écrire le jeu de tests avant d'écrire le code. Couvrir les trois familles de cas du chapitre 3.
Corrigé
Prenons le module regles, et sa fonction gagnant. Le jeu de tests s'écrit avant le code, à partir de la seule troisième ligne de la fiche de spécification.
# tests_regles.py -- ecrit AVANT regles.py
from regles import gagnant, coup_legal
V = "." # case vide, pour que les grilles restent lisibles
def test_cas_nominaux():
"""Famille 1 : les cas ordinaires, ceux qu'on avait en tete."""
assert gagnant([["X", "X", "X"], [V, V, V], [V, V, V]]) == "X"
assert gagnant([["O", V, V], ["O", V, V], ["O", V, V]]) == "O"
assert gagnant([["X", V, V], [V, "X", V], [V, V, "X"]]) == "X"
assert gagnant([[V, V, "O"], [V, "O", V], ["O", V, V]]) == "O"
def test_cas_limites():
"""Famille 2 : les bords -- grille vide, grille pleine sans gagnant."""
assert gagnant([[V, V, V], [V, V, V], [V, V, V]]) is None
nulle = [["X", "O", "X"],
["X", "O", "O"],
["O", "X", "X"]]
assert gagnant(nulle) is None
def test_cas_d_erreur():
"""Famille 3 : ce que le programme doit refuser."""
g = [["X", V, V], [V, V, V], [V, V, V]]
assert coup_legal(g, 1, 1) is True
assert coup_legal(g, 0, 0) is False, "case deja occupee"
assert coup_legal(g, 3, 0) is False, "hors grille"
assert coup_legal(g, -1, 0) is False, "indice negatif"
for test in (test_cas_nominaux, test_cas_limites, test_cas_d_erreur):
test()
print("ok", test.__name__)
Les trois familles du chapitre 3 sont ici explicites :
| Famille | Ce qu'on y met |
|---|---|
| cas nominaux | les quatre façons de gagner : ligne, colonne, et les deux diagonales |
| cas limites | la grille vide et la grille pleine sans gagnant --- les deux extrémités |
| cas d'erreur | les coups à refuser : case occupée, indices hors grille, indice négatif |
Ce que l'écriture préalable des tests a déjà rapporté. Trois décisions ont dû être prises avant la première ligne de regles.py, et elles auraient sinon été prises au hasard de l'écriture :
gagnantrendNoneet nonFalsequand personne n'a gagné — un test l'a exigé ;- une case vide se note
"."et nonNoneni0: sinon la grille n'est plus lisible dans les tests eux-mêmes ; coup_legaldoit traiter l'indice négatif, que l'on n'aurait pas pensé à interdire — en Python,g[-1]ne provoque aucune erreur, il désigne la dernière ligne. Un coup en « fonctionnerait » silencieusement.
Le troisième point est le vrai butin de l'exercice. Il n'est pas venu du code, il est venu de la question « quels cas dois-je refuser ? », posée pendant qu'on avait encore le temps d'y répondre.
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.