
Utilisation de pytest (framework de test plus avancé)
Passez à la vitesse supérieure en matière de tests unitaires avec pytest. Découvrez sa simplicité, sa puissance et ses fonctionnalités avancées (fixtures, parametrization, marqueurs, plugins) pour des tests plus efficaces et plus agréables à écrire.
pytest : un framework de test moderne et populaire
`pytest` est un framework de test pour Python qui est devenu très populaire en raison de sa simplicité, de sa flexibilité et de ses nombreuses fonctionnalités avancées.
Contrairement à `unittest` (le framework de test intégré à Python), `pytest` ne nécessite pas de créer des classes de test. Vous pouvez écrire vos tests dans de simples fonctions Python, et utiliser des assertions `assert` standard.
`pytest` offre de nombreux avantages par rapport à `unittest` :
- Syntaxe plus concise : Moins de code à écrire pour les tests.
- Découverte automatique des tests : `pytest` trouve automatiquement les tests dans votre projet (en suivant des conventions de nommage simples).
- Assertions plus expressives : Vous pouvez utiliser directement `assert` avec des expressions Python (pas besoin de méthodes spéciales comme `assertEqual`, `assertTrue`, etc.).
- Fixtures : Un mécanisme puissant pour gérer la mise en place et le nettoyage de l'environnement de test.
- Paramétrisation : Exécutez facilement le même test avec différentes données d'entrée.
- Marqueurs : Organisez et sélectionnez les tests à exécuter (par exemple, marquer des tests comme lents, ou comme nécessitant des ressources spécifiques).
- Plugins : `pytest` est extensible grâce à un système de plugins (il existe de nombreux plugins pour l'intégration avec d'autres outils, l'ajout de fonctionnalités, etc.).
- Rapports de test clairs et informatifs : `pytest` fournit des rapports de test détaillés, avec des informations sur les tests échoués, les exceptions, etc.
`pytest` est largement utilisé dans la communauté Python et est devenu un standard de facto pour les tests.
Installation et exécution de pytest
Pour utiliser `pytest`, vous devez d'abord l'installer (il n'est pas inclus dans la bibliothèque standard) :
pip install pytestPour exécuter vos tests avec `pytest`, il suffit d'exécuter la commande `pytest` dans votre terminal, à partir du répertoire racine de votre projet :
pytest`pytest` recherchera automatiquement les tests dans tous les fichiers Python dont le nom commence par `test_` ou se termine par `_test.py`, et dans toutes les fonctions dont le nom commence par `test`.
Vous pouvez également spécifier un fichier ou un répertoire spécifique :
pytest tests/test_mon_module.py
pytest tests/Ou même une fonction de test spécifique:
pytest tests/test_mon_module.py::test_ma_fonctionEcrire des tests avec pytest : fonctions de test et assertions
Avec `pytest`, vous écrivez vos tests dans des fonctions Python ordinaires, dont le nom commence par `test`. Vous utilisez l'instruction `assert` standard de Python pour vérifier les conditions.
Exemple :
# test_exemple.py
def additionner(a, b):
return a + b
def test_addition():
assert additionner(2, 3) == 5
assert additionner(0, 0) == 0
assert additionner(-1, 1) == 0Dans cet exemple :
- `test_addition` est une fonction de test.
- `assert additionner(2, 3) == 5` est une assertion. Elle vérifie que l'appel de fonction `additionner(2, 3)` retourne bien `5`.
Si une assertion échoue, `pytest` interrompt l'exécution de la fonction de test et affiche un message d'erreur détaillé, indiquant la ligne où l'assertion a échoué, la valeur attendue et la valeur réelle.
Vous pouvez utiliser n'importe quelle expression booléenne dans une assertion `assert`. `pytest` fournit des informations utiles en cas d'échec, même pour des expressions complexes.
Fixtures : gérer l'environnement de test
Les fixtures sont l'une des fonctionnalités les plus puissantes de `pytest`. Elles permettent de définir du code de configuration (setup) et de nettoyage (teardown) qui sera exécuté avant et/ou après les tests.
Les fixtures sont des fonctions Python ordinaires, décorées avec `@pytest.fixture`.
Une fixture peut :
- Retourner une valeur qui sera utilisée par les tests (par exemple, un objet, une connexion à une base de données, etc.).
- Effectuer des actions avant le test (par exemple, créer des fichiers temporaires, démarrer un serveur, etc.).
- Effectuer des actions après le test (par exemple, supprimer des fichiers temporaires, arrêter un serveur, etc.).
Pour utiliser une fixture, vous l'ajoutez simplement comme argument à votre fonction de test.
Exemple :
import pytest
@pytest.fixture
def exemple_fixture():
# Code de configuration (exécuté avant le test)
print("\nMise en place de la fixture...")
donnees = {"cle": "valeur"}
yield donnees # Fournit la valeur à utiliser dans le test
# Code de nettoyage (exécuté après le test)
print("\nNettoyage de la fixture...")
def test_avec_fixture(exemple_fixture):
# Le test reçoit la valeur retournée par la fixture
assert exemple_fixture["cle"] == "valeur"Dans cet exemple:
- `exemple_fixture` est une fixture. Elle est décorée avec `@pytest.fixture`.
- La fixture `exemple_fixture` effectue une action avant le test (affiche un message et initialise un dictionnaire), fournit une valeur au test (`donnees`) avec l'instruction `yield`, puis effectue une action après le test (affiche un message).
- La fonction de test `test_avec_fixture` prend `exemple_fixture` en argument. `pytest` s'occupe automatiquement d'appeler la fixture et de passer sa valeur de retour à la fonction de test.
Les fixtures peuvent être partagées entre plusieurs tests, et elles peuvent dépendre d'autres fixtures. `pytest` gère automatiquement l'ordre d'exécution des fixtures en fonction de leurs dépendances.
Les fixtures permettent de créer des environnements de test complexes de manière modulaire et réutilisable.
Paramétrisation : exécuter un test avec plusieurs jeux de données
La paramétrisation permet d'exécuter le même test plusieurs fois avec des données d'entrée différentes. Cela permet de tester facilement différents cas d'utilisation sans avoir à écrire plusieurs fonctions de test similaires.
En `pytest`, la paramétrisation se fait avec le décorateur `@pytest.mark.parametrize`.
Exemple :
import pytest
def additionner(a, b):
return a + b
@pytest.mark.parametrize("a, b, resultat_attendu", [
(2, 3, 5),
(0, 0, 0),
(-1, 1, 0),
(1.5, 2.5, 4.0),
])
def test_addition(a, b, resultat_attendu):
assert additionner(a, b) == resultat_attenduDans cet exemple:
- `@pytest.mark.parametrize("a, b, resultat_attendu", [...])` décore la fonction de test `test_addition`.
- Le premier argument de `parametrize` est une chaîne de caractères contenant les noms des arguments de la fonction de test, séparés par des virgules.
- Le deuxième argument de `parametrize` est une liste de tuples. Chaque tuple contient les valeurs des arguments pour un appel de la fonction de test.
Lorsque vous exécutez ce test, `pytest` exécutera la fonction `test_addition` *quatre fois*, une fois pour chaque tuple de valeurs dans la liste. Si l'une de ces exécutions échoue, `pytest` vous indiquera quelle combinaison de valeurs a provoqué l'échec.
La paramétrisation permet de tester facilement une fonction avec un large éventail de données d'entrée, sans avoir à écrire du code répétitif.
Marqueurs : organiser et sélectionner les tests
Les marqueurs permettent d'ajouter des métadonnées aux tests. Vous pouvez utiliser les marqueurs pour organiser vos tests, les sélectionner pour l'exécution, ou leur attacher des informations supplémentaires.
En `pytest`, vous pouvez utiliser le décorateur `@pytest.mark.nom_du_marqueur` pour ajouter un marqueur à une fonction de test (ou à une classe de test).
Exemple :
import pytest
@pytest.mark.lent
def test_fonction_lente():
# ...
@pytest.mark.reseau
def test_acces_reseau():
# ...
@pytest.mark.base_de_donnees
def test_acces_base_de_donnees():
# ...Vous pouvez ensuite utiliser l'option `-m` de `pytest` pour sélectionner les tests à exécuter en fonction de leurs marqueurs.
Exemples :
- Exécuter uniquement les tests marqués comme "lent" :
pytest -m lent- Exécuter les tests qui ne sont *pas* marqués comme "lent" :
pytest -m "not lent"- Exécuter les tests marqués comme "reseau" ou "base_de_donnees" :
pytest -m "reseau or base_de_donnees"`pytest` fournit quelques marqueurs prédéfinis (comme `skip`, `skipif`, `xfail`), mais vous pouvez également définir vos propres marqueurs.
Les marqueurs sont un moyen puissant d'organiser et de sélectionner les tests à exécuter.
Plugins : étendre les fonctionnalités de pytest
`pytest` a une architecture modulaire et peut être étendu grâce à des plugins. Il existe un écosystème très riche de plugins qui ajoutent des fonctionnalités, comme :
- `pytest-cov` : Mesure de la couverture de code.
- `pytest-xdist` : Exécution de tests en parallèle sur plusieurs processeurs ou machines.
- `pytest-django` : Tests pour les applications Django.
- `pytest-asyncio` : Tests pour le code asynchrone.
- `pytest-html` : Génération de rapports de test en HTML.
- Et bien d'autres...
Pour utiliser un plugin, vous devez généralement l'installer avec `pip`, puis il sera automatiquement détecté et activé par `pytest`.
Bonnes pratiques et astuces
Voici quelques conseils supplémentaires pour utiliser `pytest` efficacement :
- Utilisez des noms de fichiers et de fonctions clairs : Suivez les conventions de nommage (`test_*.py` pour les fichiers, `test_*` pour les fonctions).
- Structurez vos tests : Organisez vos tests en répertoires et sous-répertoires pour refléter la structure de votre code.
- Utilisez des fixtures : Factorisez le code de configuration et de nettoyage avec des fixtures.
- Utilisez la paramétrisation : Testez différentes combinaisons de données d'entrée avec `@pytest.mark.parametrize`.
- Utilisez des marqueurs : Organisez et sélectionnez vos tests avec `@pytest.mark`.
- Exécutez vos tests fréquemment : Intégrez l'exécution des tests dans votre flux de travail de développement (par exemple, à chaque commit, ou avant de publier une nouvelle version).
- Utilisez un outil de couverture de code : Mesurez la proportion de votre code qui est couverte par les tests (par exemple, avec `pytest-cov`).
- Lisez la documentation de `pytest` : `pytest` a une documentation très complète, avec de nombreux exemples et des explications détaillées.
`pytest` est un outil puissant et flexible qui peut vous aider à écrire des tests de meilleure qualité, plus rapidement et plus facilement.