Un exemple : on veut écrire une fonction, qui nous renvoie une valeur booléenne indiquant si on est majeur quand on a l'âge passé en paramètre.

#### Le test

D'abord le test :

```python
import unittest

class TestIsMajor(unittest.TestCase):

    def test_is_major(self):
        self.assertTrue(is_major(30))
        self.assertFalse(is_major(11))

if __name__ == '__main__':
    unittest.main()
```

Note ici une nouveauté : l'usage de `import unittest` pour, comme son nom l'indique, pouvoir utiliser les fonctionnalités fournies par un "module" ou "package" ; que ce soit un package livré en standard avec Python (comme `unittest`) ou un package installé via `pip` (comme `selenium`).

La classe `TestIsMajor` hérite de `TestCase` et de ses méthodes. Parmi celles-ci, des *assertions*, qui permettent de s'assurer qu'on obtient bien le résultat voulu.
Les deux utilisées ici, `assertTrue()` et `assertFalse()`, veulent s'assurer que l'expression qu'elles reçoivent en paramètre est respectivement vrai ou faux.

Les assertions sont souvent groupées à plusieurs dans une méthode, mais on aurait pu aussi bien remplacer `test_is_major()` par deux méthodes distinctes :

```python
    def test_is_major(self):
        self.assertTrue(is_major(30))

    def test_is_not_major(self):
        self.assertFalse(is_major(11))

```

#### Première exécution : échec attendu

Si on l'exécute tel quel (`python 06-tdd-exemple1.py`), on obtient logiquement une erreur car la fonction `is_major()` n'existe pas :
```text
E
======================================================================
ERROR: test_is_major (__main__.TestIsMajor)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "06-tdd1-test.py", line 10, in test_is_major
    self.assertTrue(is_major(30))
NameError: name 'is_major' is not defined

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)
```
A noter : le `E` isolé en première ligne nous indique que l'unique test a fini en *erreur* (ce qui est confirmé par la dernière ligne avec `errors=1`).

#### Petite amélioration...

Tentons une première amélioration, et ajoutons ces deux lignes juste au-dessous de la classe, dans le même fichier (normalement on a les **tests et le code à tester dans des fichiers séparés**) :

```python
def is_major(age):
    pass
```

Voyons ce qui se passe :
```text
F
======================================================================
FAIL: test_is_major (__main__.TestIsMajor)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "06-tdd1-test.py", line 10, in test_is_major
    self.assertTrue(is_major(30))
AssertionError: None is not true

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (failures=1)
```

Cela ne semble pas beaucoup mieux, et pourtant, on progresse... Au moins, le test a pu appeler la fonction `is_major()`.

Au lieu d'un `E` isolé en première ligne, on a un `F` pour *failure*. On nous indique en bas `failures=1`.

On a une `AssertionError` car la première assertion a échoué. La deuxième aussi aurait échoué, mais une méthode dans une classe de test est interrompue à la première assertion qui échoue.

#### Résolution :

Voici le code qui fera passer le test :
```python
def is_major(age):
    return True if age >= 18 else False
```

Résultat :
```text
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
```

&Ccedil;a a marché, et le succès est matérialisé par le `.` isolé sur la première ligne (il n'y avait qu'un test).
Cette convention (`.` pour succès, `F` pour échec, `E` pour erreur) donne un affichage compact, utile quand on a *beaucoup* de tests à faire passer.