Tests unitaires Python: démarrage rapide

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 ):

 #A simple calculator class Calculator: #empty constructor def __init__(self): pass #add method - given two numbers, return the addition def add(self, x1, x2): return x1 + x2 #multiply method - given two numbers, return the #multiplication of the two def multiply(self, x1, x2): return x1 * x2 #subtract method - given two numbers, return the value #of first value minus the second def subtract(self, x1, x2): return x1 - x2 #divide method - given two numbers, return the value #of first value divided by the second def divide(self, x1, x2): if x2 != 0: return x1/x2 

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 #Test cases to test Calulator methods #You always create a child class derived from unittest.TestCase class TestCalculator(unittest.TestCase): #setUp method is overridden from the parent class TestCase def setUp(self): self.calculator = Calculator() #Each test method starts with the keyword test_ def test_add(self): self.assertEqual(self.calculator.add(4,7), 11) def test_subtract(self): self.assertEqual(self.calculator.subtract(10,5), 5) def test_multiply(self): self.assertEqual(self.calculator.multiply(3,7), 21) def test_divide(self): self.assertEqual(self.calculator.divide(10,2), 5) # Executing the tests in the above test case class if __name__ == "__main__": unittest.main() 

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 #Test cases to test Calulator methods #You always create a child class derived from unittest.TestCase class class TestCalculator(unittest.TestCase): #setUp method overridden from the parent class TestCase def setUp(self): self.calculator = Calculator() ... def test_divide(self): self.assertEqual(self.calculator.divide(10,2), 6) # Executing the tests in the above test case class if __name__ == "__main__": unittest.main() 

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.

Source: https://habr.com/ru/post/fr481806/


All Articles