Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🐍
Intermediaire 25 min Python

Tests unitaires en Python

Pourquoi Tests unitaires en Python ?

Les tests unitaires sont essentiels pour les développeurs Python, car ils aident à garantir que chaque partie de votre code fonctionne correctement indépendamment des autres parties. En pratique quotidienne, cela signifie que vous pouvez travailler sur différents aspects du même projet sans avoir peur de régression. Par exemple, si vous ajoutez une nouvelle fonctionnalité dans un module existant, les tests unitaires peuvent détecter immédiatement si cette nouvelle fonctionnalité affecte les fonctionnalités existantes.

Prerequis

  • Connaissance de base du langage Python
  • Installation de Python (version 3.8 ou plus récente recommandée)
  • Installation de pytest pour exécuter les tests (en utilisant la commande suivante : pip install pytest)

Concepts fondamentaux

Concept 1 : Fonction assert

La fonction assert est un outil de base pour écrire des tests unitaires. Elle vérifie si une condition est vraie, sinon elle lève une exception AssertionError.


def add(a, b):
    return a + b

def test_add():
    # Vérifie que la fonction add retourne le bon résultat
    assert add(2, 3) == 5

Concept 2 : Fonctions de test

Les fonctions de test sont des fonctions qui ne font qu'un seul chose : vérifier un aspect spécifique du code. Elles doivent commencer par test_.


def test_upper():
    # Vérifie que la méthode upper() convertit une chaîne en majuscules
    assert 'foo'.upper() == 'FOO'

Concept 3 : Bibliothèque pytest

pytest est une bibliothèque populaire pour écrire et exécuter des tests unitaires. Il offre une syntaxe simple et puissante.


import pytest

def test_divide():
    # Vérifie que la division par zéro lève une exception ValueError
    with pytest.raises(ValueError):
        def divide(x, y): return x / y
        divide(10, 0)

Concept 4 : Fixtures

Les fixtures sont des fonctions qui fournissent des données ou un environnement pour les tests. Elles permettent de créer des conditions préalables avant chaque test.


import pytest

@pytest.fixture
def sample_data():
    # Retourne une liste de nombres pour les tests
    return [1, 2, 3, 4, 5]

def test_sum(sample_data):
    # Vérifie que la somme des éléments est correcte
    assert sum(sample_data) == 15

Mise en pratique : Projet fil rouge

Nous allons construire un simple gestionnaire de tâches qui permet d'ajouter, de supprimer et de lister les tâches. Voici la structure du projet :

todo_manager/
├── __init__.py
├── task.py
└── test_task.py

Étape 1 : Création des fichiers

Créez les fichiers __init__.py, task.py et test_task.py.

from .task import TaskManager
python## 

class Task:
    def __init__(self, description):
        self.description = description

class TaskManager:
    def __init__(self):
        self.tasks = []

    def add_task(self, task):
        self.tasks.append(task)

    def remove_task(self, index):
        if 0 <= index < len(self.tasks):
            del self.tasks[index]

    def list_tasks(self):
        return [task.description for task in self.tasks]
python## 

from ..task import TaskManager

def test_add_task():
    manager = TaskManager()
    manager.add_task(Task("Acheter du pain"))
    assert len(manager.list_tasks()) == 1

def test_remove_task():
    manager = TaskManager()
    manager.add_task(Task("Faire la lessive"))
    manager.remove_task(0)
    assert len(manager.list_tasks()) == 0

Étape 2 : Exécution des tests

Exécutez les tests avec pytest.

pytest todo_manager/test_task.py

Erreurs fréquentes et debugging

Erreur 1 : Test échoue sans raison

Code incorrect :

def test_upper():
    assert 'foo'.upper() == 'FOO'

Code correct :

def test_upper():
    assert 'foo'.upper() == 'FOO'  # Correct

Erreur 2 : IndexError lors de la suppression d'une tâche

Code incorrect :

def remove_task(self, index):
    del self.tasks[index]

Code correct :

def remove_task(self, index):
    if 0 <= index < len(self.tasks):
        del self.tasks[index]  # Ajout de la vérification d'index valide

Erreur 3 : Test échoue à cause d'une mauvaise implémentation

Code incorrect :

def list_tasks(self):
    return [task.description for task in self.tasks]

Code correct :

def list_tasks(self):
    return [task.description for task in self.tasks]  # Correct

Pour aller plus loin

Piste 1 : Tests pour les exceptions

Ajoutez des tests pour vérifier le comportement de votre code en cas d'exceptions.

  • Exercice : Ajouter un test pour vérifier que remove_task lève une exception si l'index est hors de portée.

Piste 2 : Mocking

Utilisez le mocking pour isoler les dépendances et tester uniquement le comportement de votre code.

  • Exercice : Utiliser unittest.mock pour simuler un appel à une autre méthode dans le gestionnaire de tâches.

Piste 3 : Couverture des tests

Améliorez la couverture de vos tests en ajoutant plus de cas d'utilisation et en testant les conditions limites.

  • Exercice : Ajouter des tests pour vérifier le comportement du gestionnaire de tâches avec une liste vide.

Défi pratique

Défi : Créer un simple API RESTful en utilisant Flask qui permet de créer, lire, mettre à jour et supprimer des tâches. Écrivez les tests unitaires pour chaque endpoint.

  • Utilisez pytest pour exécuter les tests.
  • Pour le mocking des requêtes HTTP, utilisez requests-mock.

Besoin d'aide sur Python ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Qu'est-ce que les tests unitaires en Python?
Les tests unitaires en Python sont des petits tests automatisés qui vérifient si une fonction ou un module de code fonctionne correctement.
Comment installer les bibliothèques nécessaires pour les tests unitaires en Python?
Pour installer les bibliothèques nécessaires, vous pouvez utiliser pip. La plus courante est pytest avec la commande `pip install pytest`. Si vous préférez unittest qui est intégré à Python, il n'y a pas besoin d'installation supplémentaire.
Quelle est l'avantage de faire des tests unitaires?
Les tests unitaires permettent de s'assurer que chaque partie du code fonctionne indépendamment. Ils facilitent le développement en détectant rapidement les erreurs et favorisent la refactoring en assurant que le code reste fonctionnel.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.