Ecrire simplement ses tests unitaires avec Python

Ecrire simplement ses tests unitaires avec Python

Alexandre P. dans Dev - Le 06-02-2024

Pour coder efficacement, rien de plus pratique que les tests unitaires. Aussi, je recommande chaudement de les implémenter en TDD, c'est à dire faire les tests avant voire en même temps que chaque fonction, histoire d'avoir une direction, et de coder selon un plan (input/ouput).

Commençons par installer le paquet qui permet d'exécuter les tests en python, j'ai nommé pytest

pip install pytest

Une fois que pytest est installé, vous pouvez vous lancer sans plus attendre dans l'écriture de vos tests. Je suis un fervent défenseur du TDD car coder sans anticiper l'utilisation m'a déjà causé beaucoup de soucis par le passé. Alors j'aime bien avoir une spécification des entrées et sorties écrites quelque part. Cela permet d'acter comment vous allez utiliser une fonction/méthode, etc.

Lorsque vous avez une idée sur la fonction que vous souhaitez écrire il faut se poser les questions suivantes:

  • Comment vais-je me servir de cette fonction ? (par exemple: server side, client side, etc... pour poser un cadre)
  • De quoi ai-je besoin, au minimum pour appeler cette fonction ? (quels paramètres sont obligatoires ? et de quel type ?)
  • Y a t-il des paramètres optionnels ? (cela permettra de définir combien de scénario vous aurez à minima)
  • Y a t-il plusieurs façon d'utiliser cette fonction ? (est-ce que les opérations seront différentes selon certaines conditions ? par exemple connecté ou déconnecté)

Une fois que vous avez plus ou moins une idée des réponses vous pouvez commencer l'écriture de vos tests.

Les fichiers tests doivent par convention commencer par test_. Personnellement, j'aime bien séparer en différents fichiers l'écriture de tests si nous sommes dans des cas différents, par exemple: test_lib_a_disconnected et test_lib_a_connected.

Par convention, les fonctions de tests commencent aussi par test_ Dans chaque fichier, je ferai une fonction séparée pour tester différents paramètre de ma fonction: def test_access_url_a_with_token() et def test_access_url_a_without_token()...

Voyez ces fonctions de tests comme les it en Node.js. Le nom de votre fonction doit définir ce que vous êtes sur le point de tester. A vous de mettre le curseur sur un groupe d'actions où de limiter le test à une micro opération, nécessitant ainsi, plusieurs tests pour pouvoir couvrir toutes les fonctionnalités, ainsi que les scénarios couverts.

J'ai créé l'arborescence suivante :

├── libs
│   └── reader.py
└── tests
    └── test_reader.py
    └── sample.txt

Pour que ce soit plus lisible, je vais commencer ici par là lib, donc nous ne faisons pas réellement du TDD, mais presque... Ecrivons une petite lib reader qui ne fait rien de mystique, à savoir, lire un fichier: 📄

# libs/reader.py

def read_file(filepath):
 f = open(filepath, "r")
 return f.read()

Comme il s'agit d'une lib pour lire un fichier, je vais créer un petit fichier de test dans mon répertoire de tests, sample.txt :

Lorem Ipsum is simply dummy text of the printing and typesetting industry. 
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, 
when an unknown printer took a galley of type and scrambled it to make a type specimen book. 
It has survived not only five centuries, but also the leap into electronic typesetting, 
remaining essentially unchanged. 
It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, 
and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Dans nos tests, nous allons importer notre lib reader, avec la méthode que je vous ai présenté dans cet article :

# tests/test_reader.py

import os
import sys
import os

parent_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')
sys.path.append(parent_dir)

from libs.reader import read_file

def test_reader():
  filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), './sample.txt')
  content = read_file(filepath)
  assert len(content) == 580

Pour lancer nos tests, il suffit de taper dans un terminal :

python3 -m pytest

Si jamais vous utilisez des print dans vos tests, il faut lancer pytest avec l'option -s pour que ceux-ci s'affichent, car ils sont catchés par défaut.

python3 -m pytest -s

Voilà c'était un article très simple et très basique mais qui permet de faire beaucoup de chose quand on s'y met. 😀

La prochaine fois nous allons voir comment créer des mocks avec python pour gérer les appels HTTP Rest API ou JSON-RPC, toujours dans une démarche de couverture de tests.

#python#unit tests#tdd#tests unitaires#pytest

user picture
Alexandre P.

Développeur passionné depuis plus de 20 ans, j'ai une appétence particulière pour les défis techniques et changer de technologie ne me fait pas froid aux yeux.