Quelle est la différence entre setUp()
et setUpClass()
dans le framework Python unittest
? Pourquoi la configuration serait-elle gérée d'une méthode à l'autre?
Je veux comprendre quelle partie de la configuration est effectuée dans les fonctions setUp()
et setUpClass()
, ainsi que avec tearDown()
et tearDownClass()
.
La différence se manifeste lorsque vous avez plus d'une méthode de test dans votre classe. setUpClass
et tearDownClass
sont exécutés une fois pour toute la classe; setUp
et tearDown
sont exécutés avant et après chaque méthode de test.
Par exemple:
class Example(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("setUpClass")
def setUp(self):
print("setUp")
def test1(self):
print("test1")
def test2(self):
print("test2")
def tearDown(self):
print("tearDown")
@classmethod
def tearDownClass(cls):
print("tearDownClass")
Lorsque vous exécutez ce test, il affiche:
setUpClass
setUp
test1
tearDown
.setUp
test2
tearDown
.tearDownClass
(Les points (.
) sont la sortie par défaut de unittest
quand un test réussit.) Notez que setUp
et tearDown
apparaissent avant et après test1
et test2
, alors que setUpClass
et tearDownClass
apparaissent une seule fois, au début et à la fin du test. Cas.
setUp()
et setUpClass()
dans le cadre Python unittest
?La principale différence (comme l'indiquait Benjamin Hodgson dans sa réponse) est que setUpClass
n'est appelée qu'une seule fois, c'est-à-dire avant tous les tests, tandis que setUp
est appelée immédiatement avant chaque test. (NB: il en va de même pour les méthodes équivalentes dans d'autres frameworks de test xUnit, pas seulement dans unittest
de Python.)
De la unittest
documentation :
setUpClass()
Une méthode de classe appelée avant les tests d'une classe individuelle est exécutée. setUpClass est appelé avec la classe comme seul argument et doit être décoré comme un classmethod ():
@classmethod
def setUpClass(cls):
...
et:
setUp()
Méthode appelée pour préparer le montage de test. Ceci est appelé immédiatement avant d'appeler la méthode de test; À l'exception de AssertionError ou SkipTest, toute exception déclenchée par cette méthode sera considérée comme une erreur plutôt que comme un échec de test. L'implémentation par défaut ne fait rien.
Cette partie de la question n'a pas encore reçu de réponse. Conformément à mon commentaire en réponse à la réponse de Gearon, la méthode setUp
est destinée aux éléments de la fixture communs à tous les tests (pour éviter de dupliquer ce code dans chaque test). Je trouve que cela est souvent utile, car la suppression de la duplication (généralement) améliore la lisibilité et réduit la charge de maintenance.
La méthode setUpClass
concerne les éléments coûteux que vous n’auriez à faire qu’une fois, comme ouvrir une connexion à une base de données, ouvrir un fichier temporaire sur le système de fichiers, charger une bibliothèque partagée à des fins de test, etc. test ralentirait trop la suite de tests, nous le faisons donc une fois avant tous les tests. Il s’agit d’une légère dégradation de l’indépendance des tests mais d’une optimisation nécessaire dans certaines situations. On peut soutenir que les tests unitaires ne doivent pas être réalisés de la sorte, car il est généralement possible de se moquer de la base de données/du système de fichiers/de la bibliothèque/de tout ce que vous voulez sans utiliser de choses réelles. En tant que tel, je trouve que setUpClass
est rarement nécessaire. Cependant, il est utile de tester les exemples ci-dessus (ou similaires).
Après avoir lu la question et la réponse acceptée, je pense qu’un supplément peut être ajouté.
Q: Pourquoi la configuration serait-elle gérée de l'une à l'autre?
A: C’est parce que la méthode d’essai peut avoir besoin d’être préliminaire et que celle-ci varie d’une méthode d’essai à l’autre.
Par exemple, prenez le code ci-dessous de https://www.tutorialspoint.com/unittest_framework/unittest_framework_api.htm en exemple:
import unittest
class simpleTest2(unittest.TestCase):
def setUp(self):
self.a = 10
self.b = 20
name = self.shortDescription()
if name == "add":
self.a = 10
self.b = 20
print name, self.a, self.b
if name == "sub":
self.a = 50
self.b = 60
print name, self.a, self.b
def tearDown(self):
print '\nend of test',self.shortDescription()
def testadd(self):
"""add"""
result = self.a+self.b
self.assertTrue(result == 30)
def testsub(self):
"""sub"""
result = self.a-self.b
self.assertTrue(result == -10)
if __== '__main__':
unittest.main()
La méthode testadd
et testsub
nécessite une entrée différente et nous pouvons définir la valeur de l'entrée respectivement dans la méthode setUp
.