Tests (unittest)#
courant
Module natif : aucune installation nécessaire.
Structure d'un projet testé#
Écrire un test#
# tests/test_calculs.py
import unittest
from calculs import moyenne
class TestMoyenne(unittest.TestCase):
def test_cas_nominal(self):
self.assertEqual(moyenne([2, 4, 6]), 4)
def test_liste_vide(self):
with self.assertRaises(ValueError):
moyenne([])
Lancer les tests#
python -m unittest discover # découvre tous les fichiers test_*.py
python -m unittest discover -v # détail test par test
python -m unittest tests.test_calculs.TestMoyenne.test_cas_nominal
Assertions courantes#
| Assertion | Vérifie |
|---|---|
assertEqual(a, b) |
a == b |
assertTrue(x) / assertFalse(x) |
valeur booléenne |
assertIs(a, b) / assertIsNone(x) |
identité |
assertIn(a, conteneur) |
appartenance |
assertAlmostEqual(a, b, places=7) |
égalité de flottants à une tolérance près |
assertRaises(Erreur) |
l'exception attendue est levée |
assertCountEqual(a, b) |
mêmes éléments, ordre indifférent |
Piège
Ne jamais écrire assertEqual(0.1 + 0.2, 0.3) : utiliser assertAlmostEqual, ou assertAlmostEqual(a, b, delta=1e-6) pour une tolérance absolue.
Préparation et nettoyage#
class TestSimulation(unittest.TestCase):
def setUp(self):
"""Exécuté avant chaque test."""
self.donnees = [1, 2, 3]
def tearDown(self):
"""Exécuté après chaque test, même en cas d'échec."""
...
Tests paramétrés : subTest#
class TestConversion(unittest.TestCase):
def test_valeurs(self):
cas = [(0, 32), (100, 212), (-40, -40)]
for celsius, attendu in cas:
with self.subTest(celsius=celsius): # chaque cas est rapporté séparément
self.assertAlmostEqual(vers_fahrenheit(celsius), attendu)
Ignorer un test#
@unittest.skip("non implémenté")
def test_futur(self):
...
@unittest.skipIf(sys.platform == "win32", "spécifique Unix")
def test_permissions(self):
...
doctest — tester les exemples de la docstring#
Pratique pour garantir que les exemples de documentation restent exacts, mais insuffisant comme unique suite de tests.