Une traduction de l'article a été préparée spécialement pour les étudiants du cours Python QA Engineer .
Les tests de code unitaire font partie intégrante du cycle de vie du développement logiciel. Les tests unitaires constituent également la base pour effectuer des tests de régression, c'est-à-dire qu'ils garantissent que le système se comportera conformément au scénario lorsque de nouvelles fonctionnalités sont ajoutées ou que des fonctionnalités existantes changent.
Dans cet article, je vais démontrer l'idée de base des tests unitaires dans une classe. En pratique, vous devrez écrire de nombreux cas de test, les ajouter à la suite de tests et les exécuter tous ensemble. La gestion des cas de test sera discutée dans le prochain article.
Aujourd'hui, nous allons nous concentrer sur le test du backend. Autrement dit, le développeur a implémenté un projet conformément aux spécifications (par exemple, Calculator.py), et votre tâche est de vous assurer que le code développé leur correspond vraiment (par exemple, en utilisant
TestCalculator.py
).
Supposons que vous ayez écrit la classe Calculatrice pour effectuer des fonctions de calcul de base: addition, soustraction, multiplication et division.
Le code pour cela est ici (
Calculator.py
):
Maintenant, je veux exécuter un test unitaire pour comprendre que la fonctionnalité de la classe ci-dessus fonctionne comme prévu.
Python est généralement fourni avec le package le plus complet. S'il ne se trouve pas sur votre système, utilisez pip pour l'installer.
Le test unitaire a la structure suivante:

setUp()
et
tearDown()
sont des méthodes standard
setUp()
avec le framework unittest (elles sont définies dans la classe unittest.TestCase). Selon votre scénario de test, vous pouvez remplacer ou non ces deux méthodes par défaut.
Il est temps de regarder le code du cas de test. Voici le fichier
TestCalculator.py
.
import unittest from Calculator import Calculator
Bien que ce ne soit pas nécessaire, mais en règle générale j'appelle la classe de test avec le préfixe Test (dans notre cas TestCalculator). Une exigence clé dans cette classe est la présence de la superclasse
unittest.TestCase
.
Chaque fois que ce cas de test est exécuté, la méthode setUp () est exécutée en premier. Dans notre cas, nous créons simplement un objet de la classe Calculator et l'enregistrons en tant qu'attribut de la classe. Il existe plusieurs autres méthodes par défaut dans la classe parente, dont nous discuterons plus tard.
Pour l'instant, il vous suffit d'écrire des méthodes
test_xxx
pour tester chaque méthode de la classe Calculatrice. Veuillez noter que toutes les méthodes de test commencent par le préfixe
test_
. Cela indique à Python en utilisant le cadre le plus complet que ce sont des méthodes de test.
Dans chacune des méthodes de test, j'ai utilisé la méthode
assertEqual
pour vérifier si les méthodes de la calculatrice renvoient la valeur attendue. Si la valeur de retour est égale à la valeur attendue, le test réussit, sinon il échoue.
Il existe de nombreuses méthodes d'
assert
intégrées dont nous parlerons plus tard.
La dernière ligne du code ci-dessus lance simplement le
TestCalculator
test
TestCalculator
. Il exécute chaque méthode de test définie dans la classe et renvoie le résultat.
python TestCalculator.py -v
Vous verrez une conclusion semblable à la suivante:
test_add (__main__.TestCalculator) ... ok test_divide (__main__.TestCalculator) ... ok test_multiply (__main__.TestCalculator) ... ok test_subtract (__main__.TestCalculator) ... ok -------------------------------------------------------------------- Ran 4 tests in 0.000s OK
Et si quelque chose ne fonctionne pas comme prévu?
test_divide
valeur attendue de
test_divide
de 5 à 6 (5 est la valeur correcte, maintenant nous allons voir ce qui se passe en cas d'échec. Ce n'est pas une erreur dans le code source, mais une erreur dans la suite de tests, vous pouvez également avoir des erreurs dans les suites de tests, alors vérifiez toujours testez les scripts pour les erreurs!)
import unittest from Calculator import Calculator
Lorsque vous exécutez ce scénario de test, vous obtiendrez le résultat suivant:
test_add (__main__.TestCalculator) ... ok test_divide (__main__.TestCalculator) ... FAIL test_multiply (__main__.TestCalculator) ... ok test_subtract (__main__.TestCalculator) ... ok ==================================================================== FAIL: test_divide (__main__.TestCalculator) -------------------------------------------------------------------- Traceback (most recent call last): File "TestCalculator.py", line 23, in test_divide self.assertEqual(self.calculator.divide(10,2), 6) AssertionError: 5.0 != 6 -------------------------------------------------------------------- Ran 4 tests in 0.001s FAILED (failures=1)
Il est dit ici que 3 tests sur 4 ont réussi, mais un a échoué. Dans un scénario réel, il est supposé que votre scénario de test est correct, c'est-à-dire qu'il aide ainsi à identifier une fonction qui n'est pas correctement implémentée.