Introduction
Le test est essentiel au processus de développement du logiciel, il garantit que le code fonctionne comme prévu et est exempt de défauts. En Python, pytest
est un framework de test populaire offrant plusieurs avantages sur le module unit test
standard, qui est un framework de test intégré à Python et fait partie de la bibliothèque standard. pytest
propose une syntaxe plus simple, une sortie améliorée, des fixtures puissants et une écosystème de plugins riche. Ce tutoriel vous guidera dans la configuration d’une application Flask, l’intégration de fixtures pytest
et l’écriture de tests unitaires à l’aide de pytest
.
Prérequis
Avant de commencer, vous serez nécessité de disposer des éléments suivants :
-
Un serveur fonctionnant sous Ubuntu et un utilisateur non-root avec des privilèges sudo et une firewall active. Pour des instructions sur la mise en place, veuillez sélectionner votre distribution à partir de cette liste et suivez notre guide de configuration initiale du serveur. Veuillez vous assurer de travailler avec une version supportée d’Ubuntu.
-
Familiarité avec la ligne de commande Linux. Vous pouvez consulter ce guide sur préliminaires de la ligne de commande Linux.
-
Un petit savoir-faire en programmation Python et dans le framework de test
pytest
. Vous pouvez vous référer à notre tutoriel sur le Pytest Testing Framework pour en apprendre davantage surpytest
. -
Python 3.7 ou plus élevé installé sur votre système Ubuntu. Pour apprendre comment exécuter un script Python sur Ubuntu, vous pouvez vous référer à notre tutoriel sur How to run a Python script on Ubuntu.
Why pytest
is a Better Alternative to unittest
pytest
offre plusieurs avantages sur le framework intégré unittest
:
-
Pytest vous permet d’écrire des tests avec moins de code de base, en utilisant des assertions simples au lieu des méthodes plus verbeuses requises par
unittest
. -
Il offre des sorties plus détaillées et lisibles, ce qui facilite l’identification des points de défaillance des tests.
-
Les fixations de tests de Pytest permettent des configurations de tests plus flexibles et réutilisables que les méthodes
setUp
ettearDown
d’unittest. -
Il permet de facilement exécuter la même fonction de test avec plusieurs jeux d’entrées, ce qui n’est pas aussi aisé avec
unittest
. -
Pytest dispose d’une riche collection de plugins qui étendent ses fonctionnalités, allant des outils de couverture de code à l’exécution des tests parallèles.
-
Il détecte automatiquement les fichiers de tests et les fonctions correspondant à ses conventions de nommage, économisant temps et efforts dans la gestion des suites de tests.
Compte tenu de ces avantages, pytest
est souvent le choix préféré pour les tests modernes en Python. Allons configurer une application Flask et écrire des tests unitaires en utilisant pytest
.
Étape 1 – Configuration de l’environnement
Ubuntu 24.04 embarque Python 3 par défaut. Ouvrez le terminal et exécutez la commande suivante pour vérifier la présence de Python 3 :
Si Python 3 est déjà installé sur votre machine, la commande ci-dessus retournera la version actuelle de l’installation de Python 3. Si il n’est pas installé, vous pouvez exécuter la commande suivante pour l’installer :
Ensuite, vous devez installer l’outil d’installation de packages pip
sur votre système :
Une fois pip
installé, installez Flask.
Étape 2 – Créer une application Flask
Commencez par créer une application Flask simple. Créez un nouveau répertoire pour votre projet et naviguez-y :
Maintenant, créez et activez un environnement virtuel pour gérer les dépendances :
Installez Flask en utilisant pip
:
Maintenant, créez une simple application Flask. Créez un nouveau fichier nommé app.py
et ajoutez le code suivant :
Cette application a trois routes :
/
: Retourne un simple message “Bonjour, Flask!”./about
: Retourne un simple message “Ceci est la page A propos”./multiply/<int:x>/<int:y>
: Multiplie deux entiers et retourne le résultat.
Pour exécuter l’application, exécutez la commande suivante :
A partir de l’affichage ci-dessus, vous pouvez remarquer que le serveur fonctionne sur http://127.0.0.1
et écoute sur le port 5000
. Ouvrez une autre console Ubuntu et exécutez les commandes curl
suivantes une par une :
- GET :
curl http://127.0.0.1:5000/
- GET :
curl http://127.0.0.1:5000/about
- GET :
curl http://127.0.0.1:5000/multiply/10/20
L’action effectuée par ces requêtes GET est la suivante :
-
curl http://127.0.0.1:5000/
:
Cette commande envoie une requête GET à l’URL racine (‘/’) de notre application Flask. Le serveur répond avec un objet JSON contenant le message “Hello, Flask!”, montrant ainsi la fonctionnalité de base de notre route d’accueil. -
curl http://127.0.0.1:5000/about
:
Cette commande envoie une requête GET à la route/about
. Le serveur répond avec un objet JSON contenant le message “This is the About page”. Cela montre que notre route fonctionne correctement. -
curl http://127.0.0.1:5000/multiply/10/20
:
Cette commande envoie une requête GET à la route/multiply
avec deux paramètres : 10 et 20. Le serveur multiplie ces nombres et répond avec un objet JSON contenant le résultat (200). Cela montre que notre route de multiplication peut correctement traiter les paramètres d’URL et effectuer des calculs.
Ces requêtes GET
permettent de communiquer avec les points d’accès de l’API de notre application Flask, sans modifier les données. Elles sont utiles pour récupérer des données, tester la fonctionnalité des points d’accès, et vérifier que nos routes répondent comme prévu.
Affichez maintenant chacune de ces requêtes GET
en action :
Étape 3 – Installation de pytest
et écriture de votre premier test
Maintenant que vous avez une application Flask de base, installez pytest
et écrivez quelques tests unitaires.
Installez pytest
en utilisant pip
:
Créez un dossier tests pour stocker vos fichiers de tests :
Maintenant, créez un nouveau fichier nommé test_app.py
et ajoutez le code suivant :
Division du fichier de test :
-
@pytest.fixture def client()
:
Ceci est une fonction fixture de pytest qui crée un client de test pour notre application Flask. Elle utilise la méthodeapp.test_client()
pour créer un client capable d’envoyer des demandes à notre application sans exécuter le serveur réel. L’instructionyield
permet à ce client d’être utilisé dans les tests puis d’être fermé correctement après chaque test. -
def test_home(client)
:
Cette fonction teste la route acceuil (/
) de notre application. Elle envoie une requête GET à la route en utilisant le client de test, puis elle vérifie que le code de statut de la réponse est 200 (OK) et que la réponse JSON correspond au message attendu. -
def test_about(client)
:
Commetest_home
, cette fonction teste la route à propos (/about
). Elle vérifie un code de statut de 200 et vérifie le contenu de la réponse JSON. -
def test_multiply(client)
:
Cette fonction teste la route de multiplication avec une entrée valide (/multiply/3/4
). Elle vérifie que le code de statut est 200 et que la réponse JSON contient le résultat correct de la multiplication. -
def test_multiply_invalid_input(client)
:
Cette fonction teste la route de multiplication avec une entrée invalide (multiply/three/four
). Elle vérifie que le code statut est 404 (Pas trouvé), ce qui est le comportement attendu lorsque la route ne peut pas correspondre les entrées de chaîne aux paramètres entiers requis. -
def test_non_existent_route(client)
:
Cette fonction teste le comportement de l’application lorsqu’une route inexistante est accédée. Elle envoie une requête GET vers/non-existent
, qui n’est pas définie dans notre application Flask. Le test vérifie que le code statut de la réponse est 404 (Pas trouvé), garantissant que notre application traite correctement les requêtes vers des routes non définies.
Ces tests couvrent les fonctionnalités de base de notre application Flask, garantissant que chaque route répond correctement aux entrées valides et que la route de multiplication traite les entrées invalides appropriément. En utilisant pytest
, nous pouvons facilement exécuter ces tests pour vérifier que notre application fonctionne comme prévu.
Step 4 – Exécution des tests
Pour exécuter les tests, exécutez la commande suivante :
Par défaut, le processus de découverte de pytest
recherche récursivement les fichiers commençant par « test_ » ou se terminant par « _test » dans le dossier courant et ses sous-dossiers. Les tests situés dans ces fichiers sont ensuite exécutés. Vous devriez voir un affichage similaire à :
Cela indique que tout les tests ont été passés avec succès.
Étape 5 : Utiliser des fixations dans pytest
Les fixations sont des fonctions utilisées pour fournir des données ou des ressources aux tests. Elles peuvent être utilisées pour configurer et déconfigurer des environnements de test, charger des données ou effectuer d’autres tâches de configuration. Dans pytest
, les fixations sont définies en utilisant le décorateur @pytest.fixture
.
Voici comment améliorer la fixation existante. Mettez à jour la fixation du client pour utiliser de la logique de configuration et de déconfiguration :
Cet ensemble de configurations ajoute des instructions d’affichage pour démontrer les phases d’installation et de démontage dans les sorties de tests. Ces instructions peuvent être remplacées par du code de gestion des ressources réelles si nécessaire.
essayons de lancer les tests à nouveau :
Le flag -v
augmente la verbosité, et le flag -s
permet l’affichage des instructions d’affichage dans la sortie de la console.
Vous devriez voir l’affichage suivant :
Étape 6 : Ajout d’un cas de test d’échec
Ajoutons un cas de test d’échec au fichier de tests existant. Modifiez le fichier test_app.py
et ajoutez la fonction ci-après à la fin pour un cas de test d’échec de résultat incorrect :
Divisons la fonction test_multiply_edge_cases
et expliquons ce que chaque partie fait :
-
Test avec zéro :
Ce test vérifie si la fonction de multiplication gère correctement la multiplication par zéro. Nous attendons un résultat de 0 lorsque nous multiplions n’importe quel nombre par zéro. C’est un cas extrême important à tester parce que certaines implémentations pourraient avoir des problèmes avec la multiplication par zéro. -
Test avec des nombres importants :
Ce test vérifie si la fonction de multiplication peut gérer des nombres importants sans débordement ou sans problème de précision. Nous multiplions deux valeurs de un million, attendant un résultat de un billion. Ce test est crucial car il vérifie les limites supérieures des capacités de la fonction. Notez que cela pourrait échouer si l’implémentation du serveur ne gère pas correctement les grands nombres, ce qui pourrait indiquer la nécessité d’utiliser des bibliothèques pour les nombres grands ou un type de données différent. -
Test prévu pour échouer :
Ce test est délibérément configuré pour échouer. Il vérifie si 2 * 3 égal 7, ce qui est incorrect. Ce test a pour but de montrer comment un test échouant apparaît dans la sortie de test. Cela permet de mieux comprendre comment identifier et débugger les tests échouants, ce qui est une compétence essentielle dans le développement guidé par les tests et les processus de débogage.
En incluant ces cas limites et un échec intentionnel, vous testez non seulement la fonctionnalité de base de votre route de multiplication, mais aussi son comportement dans des conditions extrêmes et ses capacités de rapport d’erreurs. Cette approche de test aide à assurer la robustesse et la fiabilité de notre application.
Faisons en sorte de relancer les tests à nouveau :
Vous devriez voir la sortie suivante :
Le message d’échec ci-dessus indique que le test test_multiply_edge_cases
dans le fichier tests/test_app.py
a échoué. Plus précisément, la dernière assertion dans cette fonction de test a causé l’échec.
Cet échec intentionnel est utile pour montrer comment les échecs de test sont rapportés et quels informations sont fournies dans le message d’échec. Il montre la ligne exacte où l’échec s’est produit, les valeurs attendues et actuelles, et la différence entre les deux.
Dans une scénario réel, vous corrigeriez le code pour que le test passe ou ajusteriez le test si le résultat attendu était incorrect. Cependant, dans ce cas, l’échec est intentionnel pour des raisons éducatives.
Conclusion
Dans ce tutoriel, nous avons vu comment configurer des tests unitaires pour une application Flask en utilisant pytest
, des fixures pytest
intégrées et montré ce que doit ressembler un échec de test. En suivant ces étapes, vous pouvez être sûr que vos applications Flask sont fiables et maintenables, en réduisant le nombre de bugs et en améliorant la qualité du code.
Vous pouvez vous référer à la documentation officielle de Flask et de Pytest pour en savoir plus.
Source:
https://www.digitalocean.com/community/tutorials/unit-test-in-flask