Débuggez Pytest
Si vous ne trouvez pas pourquoi un test échoue, vous allez forcément devoir débugger le test. Pour cela, vous aurez besoin des astuces que nous verrons dans ce chapitre.
Prenons la méthode soustraction de la classeOperators
du projet Calculatrice :
def substraction(self, operation):
self.operation = operation
self.signe = "-"
if self._is_operation_valid():
self._calculate_substraction()
return self.result
Et vérifions le scénario ci-dessous :
def test_substraction_operation():
sut = Operators()
operation = "5.5 + 10 - 10"
expected_value = 5.6
assert sut.substraction(operation) == expected_value
Après avoir exécuté la commande qui permet de lancer les tests, je me rends compte que le test ne passe pas. Pour avoir plus de détails dans le test, nous pouvons ajouter desprint
. Je vais donc retirer l’assertion et mettre desprint()
pour avoir plus de détails sur le comportement du test.
def test_substraction_operation():
sut = Operators()
operation = "5.5 + 10 - 10"
expected_value = 5.6
sut.substraction(operation)
print(f"operation : {sut.operation}")
print(f"signe : {sut.signe}")
print(f"result : {sut.result}")
print(f"expected value : {expected_value}")
Mais si vous lancez une nouvelle fois les tests avec la commandepytest
, rien ne s'affichera. Vous devez ajouter un-s
à la fin pour que s'impriment lesprint()
dans votre terminal, comme ceci :pytest -s
.
Vous pouvez également lancer la commande suivante pour exécuter simplement le scénariotest_substraction_operation
:
pytest -s tests/test_operators.py::test_substraction_operation
Si vous avez plusieurs tests dans votre fichier ou projet, cette méthode peut être très utile dans une phase de débugging.
Grâce auxprint()
que nous avons ajoutés dans le test, je me rends compte que je suis en train de tester un scénario concernant l’opérateur de soustraction, mais que l’opération contient l’opérateur d’addition.
Nous pouvons désormais écrire :
def test_substraction_operation():
sut = Operators()
operation = "5.5 - 10 - 10"
expected_value = -14.5
assert sut.substraction(operation) == expected_value
Le test passe maintenant !
Testez une exception
Il est parfois nécessaire de vérifier si une exception est correctement soulevée dans le code. Et vous avez de la chance, il existe une méthode rien que pour ça.
Considérons une fonction qui permet d’effectuer la division de deux nombres passés en argument :
def division(numerator, denominator):
return numerator / denominator
Ce code pourrait effectivement soulever une exception dans le cas d’une division par zéro. C'est pourquoi nous n'allons pas tester que le code est censé échouer, mais bien qu'il soulève une exception dans ce cas précis.
Comment faire ?
En lançant un test avec des valeurs non attendues et en constatant l'exception levée ! Pytest propose une méthode, raises(SomeException), qui spécifie que nous attendons que le programme lève une erreur.
Afin de pouvoir l'utiliser, il nous faut auparavant importer le modulepytest
.
Ajoutez donc ceci en haut de votre fichier de test :
import pytest
Puis nous pouvons écrire le test suivant :
def test_division():
numerator = 2
denominator = 0
with pytest.raises(ZeroDivisionError):
division(numerator, denominator)
Est-ce que l’exception est bien levée pour vous ? Suivez-moi dans le screencast ci-dessous pour en savoir plus sur comment tester les exceptions.
Créez des tests paramétriques
Si vous souhaitez exécuter un test avec différentes données pour vérifier son comportement, ne cherchez pas plus loin, vous avez besoin des tests paramétriques. Les tests paramétriques permettent de lancer un même scénario sur un échantillon de données. Cette méthode vous évitera de dupliquer votre test afin de le lancer avec plusieurs paramètres.
Pytest nous propose justement un décorateur qui nous permettra de mettre en place les tests paramétriques@pytest.mark.parametrize
.
Comment faire ?
Importez le module
pytest
en haut du fichier de test.Spécifiez les différents noms des paramètres dans une chaîne de caractères séparés par une virgule et placez cette chaîne de caractères en tant que premier argument du décorateur.
Indiquez les différents paramètres dans une liste de tuples et placez-la en deuxième argument du décorateur.
Définissez votre test en plaçant chaque nom de paramètre en tant qu’argument de la fonction.
Nous pouvons maintenant écrire notre premier test paramétrique :
import pytest
@pytest.mark.parametrize("number, square", [(2, 4), (10, 100), (16, 256)])
def test_should_return_square(number, square):
assert number ** 2 == square
Voici un screencast qui vous montre la mise en place pas à pas de ce test paramétrique :
À vous de jouer !
Vous pouvez maintenant reprendre le projet Calculatrice pour mettre en place vos premiers tests paramétriques.
Retrouvez une proposition de correction sur le projet super-calculatrice !
En résumé
L’option
-s
lorsque vous lancez la commandepytest
permet d’afficher lesprint
du test sur le terminal :pytest -s
.Pour tester une exception soulevée dans le code, il faut utiliser la fonction
raises()
qui est fournie par le modulepytest
. Si le bloc de code contenu dans le blocwith
ne soulève pas d’exception, il ne sera pas validé.Les tests paramétriques permettent de lancer un même scénario sur un échantillon de données. Vous devez définir dans le décorateur
@pytest.mark.parametrize
l’échantillon de données à distribuer.
C’est terminé pour cette partie 2, l’heure du quiz a sonné ! Je vous mets au défi de trouver un minimum de 7 bonnes réponses.