Qu’est-ce qu’un test unitaire ?
Un test unitaire est un petit programme qui appelle une seule fonction avec un cas précis, puis vérifie le résultat. Il vous dit en une seconde si la fonction marche encore après chaque changement.
Une médiathèque calcule l’amende d’un livre rendu en retard. Si la règle change, vous voulez le savoir avant le passage en caisse, pas après.
À la fin de cette leçon
Remarque
Je peux écrire un test unitaire avec des assertions et le lancer avec unittest.
Mots-clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Test unitaire | un petit test qui appelle une seule fonction | |
| Assertion | une vérification qui échoue si la condition est fausse | assert amende(0) == 0 |
| Préparer, agir, vérifier | les trois temps d’un test : les données, l’appel, la comparaison | |
| Échec | un test dont l’assertion est fausse | |
| Erreur | un test qui s’arrête parce que le code lève une exception | |
| unittest | le module de Python qui range les tests et les lance |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un test a trois temps : préparer, agir, vérifier
D’abord vous préparez les données : ici, un nombre de jours de retard. Ensuite vous agissez : vous appelez la fonction. Enfin vous vérifiez : vous comparez le résultat à la valeur attendue.
Cette dernière étape est l’assertion. Si elle est fausse, le test échoue et dit pourquoi.
La règle de l’amende à tester
Voici la règle de la médiathèque, en centimes pour éviter les nombres décimaux. Un livre rendu à temps ne coûte rien. Chaque jour de retard coûte 20 centimes, et l’amende ne dépasse jamais 600 centimes.
Trois assertions simples
def amende(jours_de_retard):
if jours_de_retard <= 0:
return 0
total = 20 * jours_de_retard
if total > 600:
return 600
return total
# Préparer, agir, vérifier : une ligne par assertion.
assert amende(0) == 0
assert amende(3) == 60
assert amende(100) == 600
print("Les trois assertions sont vraies")
unittest range les tests dans une classe
Python fournit unittest. Un fichier de tests importe la fonction et définit une classe dont chaque méthode test_... est un test.
assertEqual(obtenu, attendu) compare deux valeurs et fait échouer le test si elles diffèrent. Le nom d’un test dit ce qu’il vérifie.
Un fichier de tests avec unittest
import unittest
from mediatheque import amende
class TestsAmende(unittest.TestCase):
def test_pas_de_retard(self):
self.assertEqual(amende(0), 0)
def test_trois_jours(self):
self.assertEqual(amende(3), 60)
def test_plafond(self):
self.assertEqual(amende(100), 600)
unittest dans le terminal, assert dans les devoirs
Dans le terminal du labo, vous utiliserez unittest, qui sait lancer tous les tests d’un dossier. Dans les devoirs de la plateforme, les tests cachés sont de simples fonctions test_... qui contiennent des assert.
L’idée est la même : un cas, un appel, une comparaison.
Créer un dossier pour les essais
mkdir -p essaisAffiché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.
Écrire la fonction à tester
printf 'def amende(jours_de_retard):\n if jours_de_retard <= 0:\n return 0\n total = 20 * jours_de_retard\n if total > 600:\n return 600\n return total\n' > essais/mediatheque.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.
Écrire les trois tests
printf 'import unittest\nfrom mediatheque import amende\n\n\nclass TestsAmende(unittest.TestCase):\n def test_pas_de_retard(self):\n self.assertEqual(amende(0), 0)\n\n def test_trois_jours(self):\n self.assertEqual(amende(3), 60)\n\n def test_plafond(self):\n self.assertEqual(amende(100), 600)\n' > essais/test_mediatheque.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.
Lancer les tests : la dernière ligne est OK
python3 -m unittest discover -s essais 2>&1 | tail -1Affiché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 test qui échoue dit où et pourquoi
Un test sert surtout quand il échoue. Remplaçons la fonction par une version sans plafond : la faute est de ne pas limiter l’amende.
Le test test_plafond doit alors échouer. Le message donne la valeur obtenue puis la valeur attendue.
Remplacer la fonction par une version fautive
printf 'def amende(jours_de_retard):\n if jours_de_retard <= 0:\n return 0\n return 20 * jours_de_retard\n' > essais/mediatheque.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.
Lancer les tests : un échec
python3 -m unittest discover -s essais 2>&1 | tail -1Affiché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 le message de l’échec
python3 -m unittest discover -s essais 2>&1 | grep AssertionErrorAffiché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 un échec : obtenu, puis attendu
La dernière ligne est FAILED (failures=1). Un test a échoué sur trois. Le message est AssertionError: 2000 != 600.
Le test appelait amende(100). La fonction a rendu 2000 centimes, et le test attendait 600. La faute est donc dans le plafond.
Erreur fréquente
Attention
Un test sans assertion passe toujours, même si la fonction est fausse : il ne vérifie rien. Après avoir écrit un test, vérifiez qu’il peut échouer. Pour cela, cassez la fonction un instant.
Écrire la fonction que les tests décrivent
Dans le devoir, vous recevez la règle des photocopies de la médiathèque : 10 centimes la page pour les 20 premières, puis 5 centimes la page. Les tests cachés appellent votre fonction avec 0, 1, 20, 21 et 100 pages.
Pensez aux deux tarifs, et à ce qui change à la page 21.