Cours
Les tests vous donnent l'assurance que votre code fait bien ce que vous attendez. Dans ce tutoriel, nous allons découvrir les bases du développement piloté par les tests (TDD) en Python. Pour commencer, nous verrons ce qu'est le TDD et pourquoi écrire les tests en premier facilite l'écriture du code. Nous adopterons une approche "test-first" : nous écrirons d'abord des cas de test qui échouent pour la fonctionnalité à implémenter, avant de réaliser la fonction elle-même.
Prérequis du tutoriel
Pour ce tutoriel, il vous faut une compréhension de base de Python. Si vous souhaitez vous remettre à niveau, consultez ce cours : Introduction to Python for Developers.
Une approche test-first nous oblige à réfléchir au comportement attendu et aux sorties prévues. Vous pouvez utiliser plusieurs bibliothèques pour tester en Python, comme pytest et unnitest. Cependant, pour l'instant, nous allons nous concentrer sur l'écriture de cas de test simples en Python natif afin de vérifier que la fonctionnalité souhaitée produit bien le résultat attendu.
Nous commencerons par un cas de test simple, puis nous étendrons progressivement les cas pour couvrir différents scénarios. En enrichissant nos tests, nous pourrions détecter des bogues ou des lacunes dans notre logique initiale à améliorer. Ce cycle consistant à écrire des tests plus avancés, les voir échouer, puis améliorer l'implémentation est au cœur du développement piloté par les tests avec Python.
Pour ce tutoriel, nous utiliserons DataLab, le notebook de données cloud de DataCamp qui vous permet d'écrire et d'exécuter du code Python sans rien installer en local. Allons-y !
Premiers pas avec DataLab
Avant de nous lancer dans le développement piloté par les tests, prenons en main DataLab pour comprendre comment l'utiliser tout au long de l'apprentissage. En ouvrant DataLab, vous verrez de nombreuses options. Pour l'instant, nous allons nous concentrer sur l'écriture de Python dans DataLab.

Si vous sélectionnez Python, le classeur ouvre une cellule de code prête à accueillir votre code Python. Elle ressemblera à ceci :

Plusieurs options utiles sont disponibles ici. Vous pouvez, par exemple, exécuter la cellule pour produire une sortie, ajouter des commentaires ou des notes pour soutenir votre apprentissage et utiliser l'IA pour vous aider à démarrer ou à vous débloquer. Vous pouvez également ajouter ou supprimer autant de cellules que nécessaire. Nous allons nous concentrer sur l'exécution de la cellule avec l'option "Run". Comme vous pouvez le voir dans le code ci-dessous, toute sortie générée par votre code s'affiche sous la cellule au moment de l'exécution.
Remarque rapide : si vous utilisez plusieurs cellules et que vous avez défini une variable dans l'une, mais tentez d'y accéder depuis une autre, vous devez exécuter chaque cellule séparément ou exécuter tout le classeur (via le bouton "Run" en haut à droite du classeur).

Maintenant que nous avons vu les bases de DataLab, passons au développement piloté par les tests.
Développement piloté par les tests
Le développement piloté par les tests consiste à écrire les tests de votre code avant d'écrire le code lui-même. Pour expliquer le TDD, commençons par un exemple très simple qui consiste à écrire un script Python pour additionner des nombres. Toutefois, avant d'écrire la fonction, nous allons écrire un test pour vérifier que 1 + 1 égale 2. Vous pouvez le faire en Python natif, comme ci-dessous.
assert 1 + 1 == 2
Le mot-clé assert en Python sert à écrire des cas de test et à confirmer que les conditions du programme s'évaluent à True. Il permet de valider le comportement et les sorties de votre code. Lorsqu'une instruction assert échoue, elle lève une AssertionError, signalant un problème dans le code. Dans votre classeur DataLab, cela ressemblerait à ceci :

Exemple 1 : tester une fonction simple
Commençons par le test. Ouvrez un fichier Python dans DataLab. Le développement piloté par les tests commence par écrire un test qui échoue. Écrivons donc un test qui échoue en appelant la fonction add(), qui n'a pas encore été définie.
assert add(1, 1) == 2
Cela entraînera une NameError, indiquant qu'il n'existe aucune implémentation : c'est l'étape "rouge". Vous obtenez une NameError lorsque vous tentez d'appeler une fonction ou une variable non définie.

Passons maintenant à l'implémentation de la fonction. Nous pouvons le faire en définissant la fonction :
def add(num1, num2):
return
Nous avons défini notre fonction add, qui prend deux paramètres, num1 et num2. Notre fonction ne renvoie encore rien. Voyons si cette implémentation passe nos tests !

Nous ne voyons plus de NameError. Toutefois, l'exécution de la cellule produit toujours une erreur ! Cette fois, c'est une AssertionError. Le test échoue donc encore. Pourquoi cette erreur ? Parce que nous avons défini une fonction qui ne renvoie encore aucune valeur.
Lors de l'exécution du test, nous obtenons une AssertionError car 1 + 1 n'égale pas 2 avec notre implémentation vide. Nous pouvons enfin faire passer le test en implémentant correctement la logique dans la fonction.

Vous remarquerez le point vert dans le coin de la cellule. Il indique que votre code est valide et qu'il a réussi lorsque vous exécutez la cellule. Auparavant, il était rouge avec une erreur d'exécution et affichait le type d'erreur sous la cellule. Cette fonctionnalité est utile pour déboguer votre code dans DataLab.
Vous venez d'écrire votre premier test en Python avec une approche pilotée par les tests. Bravo ! Passons maintenant à l'élargissement de nos tests et à la réflexion sur les erreurs potentielles qui pourraient faire échouer notre fonction ou l'empêcher de produire le résultat attendu.
Exemple 2 : plusieurs cas de test
Tester avec un seul jeu de valeurs permet rarement de déceler toutes les erreurs potentielles. Des bogues peuvent facilement se cacher, surtout si votre fonction repose sur des entrées variables de l'utilisateur ou une logique externe. Comment tester de manière exhaustive une fonction avec plusieurs valeurs ?
Par exemple, que se passe-t-il si un type de données incorrect est passé à la fonction ? Vous pourriez utiliser des frameworks de test Python, mais restons sur du Python de base. Je définis d'abord une liste de dictionnaires d'entrée pour simuler différents scénarios d'usage :
test_cases = [
{"num1": 1, "num2": 3, "expected": 4},
{"num1": 1, "num2": "invalid", "expected": "Error: num2 must be a number"},
{"num1": [1,2,3], "num2": 2, "expected": "Error: num1 must be a number"},
{"num1": -1, "num2": 1, "expected": 0},
{"num1": 3.5, "num2": 2.5, "expected": 6.0},
{"num1": 100, "num2": 200, "expected": 300}
]
Le code ci-dessus présente des entrées pour la fonction ainsi que les résultats attendus. Il nous faut toutefois mettre à jour notre test pour itérer sur ces cas. Nous pouvons valider chaque dictionnaire de la liste en imbriquant l'assertion dans une boucle for.
for test in test_cases:
assert add(test["num1"], test["num2"]) == test["expected"]
Puisque la fonction est inchangée, doit-on s'attendre à ce que ce test réussisse ou échoue ? Et quelle erreur pourrait survenir ?

Le test lève une TypeError car nous n'avons pas géré les entrées non numériques : et si une chaîne de caractères ou un booléen était passé au lieu d'un int ? Nous pouvons mettre à jour la fonction pour traiter ces cas ! En vérifiant que l'entrée est un entier ou un flottant, nous pouvons renvoyer un message personnalisé pour les types invalides.
def add(num1, num2):
if type(num1) is not int and type(num1) is not float:
return "Error: num1 must be a number"
elif type(num2) is not int and type(num2) is not float:
return "Error: num2 must be a number"
else:
return num1 + num2
En relançant nos tests, nous n'obtenons plus d'erreurs : les tests ont réussi. Le cercle vert indique que nous avons désormais des tests au vert. Bien joué !

Pour conclure
Dans ce tutoriel, nous avons passé en revue les fondamentaux du développement piloté par les tests en Python avec DataLab. DataLab offre un IDE cloud qui permet d'écrire et d'exécuter du code Python sans installation locale. Les tests valident le comportement du code et détectent les erreurs tôt. Les assertions vérifient des conditions et lèvent des exceptions en cas d'échec.
Vous pouvez explorer d'autres cas de test et commencer à écrire les vôtres dans DataLab ! Pour aller plus loin sur le test en Python, découvrez notre cours DataCamp : Introduction to Testing in Python.
Amina est stagiaire en développement de contenu chez Datacamp. Après une formation en architecture et en éducation, elle a changé de carrière pour se consacrer au développement de logiciels, en commençant par JavaScript ; elle se concentre maintenant sur Python.
