02 Test unitaire & d'intégration
A partir de maintenant nous nous servirons toujours du même projet pour la suite des TDs.
Et les tests dans tout ça ?
Déjà un TD sur les tests unitaires et d'intégrations ? Si tôt dans la découverte de Python et Flask ?
Et oui ! C'est bien beau de parler de TDD mais encore faut il le mettre en place et savoir en faire.
Plutôt que de tout tester à la main de maniére répétitif et fastidieuse, nous allons apprendre à les automatiser pour notre plus grand bonheur 😀.
Pré requis
Pour réaliser les tests unitaires et d'intégrations nous aurons besoin de la librairie ... pytest.
pipenv install pytest
Structure de notre dossier
En reprenant la structure de notre projet vous devriez avoir:
-- app.py
-- Pipfile
-- Pipfile.lock
Nous allons donc créer un répertoire tests à la racine de notre projet qui contiendra nos fichier de tests:
-- tests/
+-- __init__.py
+-- test_functions.py
+-- test_integrations.py
-- app.py
-- Pipfile
-- Pipfile.lock
Premier test unitaire
L'exemple le plus simple pour comprendre le principe des tests unitaires est la fonction de multiplication.
Pour rappel une multiplication est l'opération mathématique permettant d'obtenir le produit de deux facteur (nommés facteur gauche et facteur droite).
Création d'un premier test unitaire
Dans le fichier tests/test_functions.py
ajouter le code suivant:
import pytest
def test_multiplication():
assert 4 == multiplication(2, 2)
Lancez les tests via la commande
pytest --disable-warnings
Normalement vous devriez avoir l'erreur suivante :
$ pytest tests/ --disable-warnings
============================================= test session starts ======================================
tests/test_functions.py F [100%]
================================================== FAILURES ============================================
_____________________________________________ test_multiplication ______________________________________
def test_multiplication():
> assert 4 == multiplication(2, 2)
E NameError: name 'multiplication' is not defined
tests/test_functions.py:5: NameError
========================================== 1 failed in 0.03 seconds ====================================
C'est normal ! Nous respectons la philosophie TDD à savoir écrire nos tests d'abord puis vérifier que ceux-ci échouent !
Il convient de créer maintenant notre fonction de multiplication, pour plus de simplicité nous allons créer un module python maths
qui contiendra un sous module algebra:
-- tests/
+-- __init__.py
+-- test_functions.py
+-- test_integrations.py
-- maths/
+-- __init__.py
+-- algebra.py
-- app.py
-- Pipfile
-- Pipfile.lock
Le code du module math étant au combien complexe (l'erreur de code est volontaire ne la corriger pas):
def multiplication(left_factor, right_factor):
return left_factor + right_factor
Si on relance notre test (pensez à ajouter un import de la fonction multiplication), celui-ci .. passe ! Mais notre jeu de données n'est pas complet ! Il convient donc d'ajouter une assertion supplémentaire à notre test.
- Ajoutez l'assertion dans notre test que le produit de 3 par 7 est 21
- Relancez votre test que constatez vous ?
- Corrigez le code de votre fonction pour régler ce souci.
Bravo vous venez de faire votre première suite de test unitaire 🎉.
Remarque
Le répertoire tests/
ainsi que le fait de préfixer nos fichier par test_*
est une convention qui permet à pytest de charger de manière automatique l'ensemble des tests du répertoire.
À vous de jouer
- Créer la suite de tests unitaires pour les opérations arithmétique de base (division, soustraction, addition).
Test d'intégration
Tester nos fonctions c'est bien, utile et indispensable. Toutefois il est tout aussi indispensable de tester le retour de nos pages, nous allons donc voir comment mettre en place des tests d'intégrations.
Création d'un client de test
Dans le fichier test_integrations.py
du répertoire tests/
import os
import pytest
from app import app
from flask import url_for
@pytest.fixture
def client():
app.config['TESTING'] = True
app.config['SERVER_NAME'] = 'TEST'
client = app.test_client()
with app.app_context():
pass
app.app_context().push()
yield client
Notre premier test d'intégration
Ajouter le test d'intégration suivant dans le fichier:
def test_index(client):
rv = client.get('/')
assert rv.status_code == 200
assert b'Hello, World!' in rv.data
Le test d'intégration test_index permet de:
- Tester si le retour de la requête sur / en méthode GET retourne le code de statut 200,
- Et que le contenu de la réponse est bien Hello, World!.
- Lancez la suite de tests,
- Que constatez vous ?
Vous savez désormais tester en intégration une page de votre site web.
Un test un peu plus complexe
- Comment mettre en place un test d'intégration pour la route hello de votre site ? Pensez à l'esprit TDD et comment tester cela.