J'utilise le module Python Unittest pour effectuer plusieurs tests; Cependant, il est très répétitif.
J'ai beaucoup de données que je veux passer à travers le même test, vérifier si vous vérifiez s'il est correct. Cependant, je dois définir un test pour chacun. P>
Par exemple, je veux faire quelque chose de similaire à cela. Je sais que je pouvais le faire à l'aide d'un générateur (trouvé dans un fil précédent ici). Mais existe-t-il des alternatives, peut-être même utiliser un module de test différent? P>
Toute suggestion serait géniale. P>
7 Réponses :
Le problème avec les affirmations de fonctionnement dans une boucle est que, si l'une des affirmations échoue, vous ne savez pas quelle valeur le faisait (dans votre exemple, cela échouerait sur Ce que je fais dans mon test consiste à créer un simple, peu de temps Nommé la fonction interne à l'intérieur du test et l'appelez avec différents arguments. Donc, votre fonction ressemblerait à ceci: p> de cette façon, lorsque l'affirmation échoue à 0 code>, mais vous Je ne sais pas que tant que vous déboguez). D'autre part, répéter
self.assertequal (i, 33) code> est une idée encore pire, car elle introduit la duplication de code.
0 code>, vous le voyez immédiatement sur la trace de la pile imprimée par le module
unittest code>. p> p>
Je vois ce que tu fais. C'est une bonne idée. Mais la première fois qu'elle frappe 33, cela cessera d'exécuter pour le reste du code.
Si ce que vous dites, c'est que vous devez recréer le dispositif de test pour chaque numéro, vous devriez aller de l'avant sur ce que Bill Gribble a suggéré et de construire de manière dynamique un testse.
Vous voudrez peut-être envisager d'utiliser la classe Unitest.TestSsuite, qui vous permettra de construire de manière dynamique un ensemble d'instances unitest.descycase qui seront exécutées séparément. Votre sous-classe Unitest.ESTeCase doit définir une seule méthode d'essai, la classe acceptant un paramètre de construction passant de la valeur à tester pour ce cas particulier. p>
Un exemple de code pour la solution suggéré par Bill Gribble pourrait ressembler à ceci:
import unittest class DataTestCase(unittest.TestCase): def __init__(self, number): unittest.TestCase.__init__(self, methodName='testOneNumber') self.number = number def testOneNumber(self): self.assertEqual(self.number, 33) def shortDescription(self): # We need to distinguish between instances of this test case. return 'DataTestCase for number %d' % self.number def get_test_data_suite(): numbers = [0,11,222,33,44,555,6,77,8,9999] return unittest.TestSuite([DataTestCase(n) for n in numbers]) if __name__ == '__main__': testRunner = unittest.TextTestRunner() testRunner.run(get_test_data_suite())
Dans un autre message, j'ai trébuché Tests de nez Il est plus adapté aux tests basés sur les données.
class Test_data(): def testNumbers(): numbers = [0,11,222,33,44,555,6,77,8,9999] for i in numbers: yield checkNumber, num def checkNumber(num): assert num == 33
the Par exemple: p> et lorsque vous l'exécutez, vous obtenez 4 tests au lieu d'une seule: p> avis que ddt em> essaie de proposer des noms pour les TC générés. p> Installez-le avec PIP: P> [*] La même solution pour le cadre Pythonic ddt code> bibliothèque
a été construit pour résoudre exactement ce que vous demandez Unittest code> [*].
Pytest Code> Framework (
Pytest.mark.Parametrizetrize code>) est intégré à l'outil Core, et vaut la peine de passer à
Pytest code> juste pour cette fonctionnalité seule. p> p>
Spin-off de Cette réponse, qui ne fonctionnait pas vraiment pour moi. Où je ne traite pas de gros em> les quantités de données, j'ai besoin d'exécuter les mêmes tests avec des entrées différentes. Les tests suivants utilisent L'exigence est d'exécuter les deux tests avec la même personnalisation. P> create_a code> et
cotisation_b code> que je veux personnaliser.
class Tests(unittest.TestCase):
def __init__(self, create_a, create_b):
super().__init__()
self.create_b = create_b
self.create_a = create_a
def test_a_uses_b(self):
a = self.create_a()
b = self.create_b()
a.b = b
self.assertIs(b.a, a)
def test_b_uses_a(self):
a = self.create_a()
b = self.create_b()
b.a = a
self.assertIs(a.b, b)
class TestPair1(Tests):
def __init__(self):
super().__init__(create_a1, create_b1)
class TestPair2(Tests):
def __init__(self):
super().__init__(create_a2, create_b2)
AS de Python 3.4 Vous pouvez utiliser Voici votre exemple modifié pour utiliser Unitest.ESTCASE.SubTest (msg = nul, ** paramètres) code> Context Manager ( Documentation ). Cela vous permettra de réaliser ce que vous voulez en ajoutant une seule déclaration.
sous-test () code> p>
import unittest
class TestData(unittest.TestCase):
def testNumbers(self):
numbers = [0, 11, 222, 33, 44, 555, 6, 77, 8, 9999]
for i in numbers:
with self.subTest(i=i): # added statement
self.assertEqual(i, 33)
Cette réponse est exactement ce que l'OP (et i) nécessaire avec des réécrites minimes.
Quel est le problème avec ça? Cela semble très bien.
Fondamentalement, dès que l'affirmation est vraie, elle cessera d'exécuter.