12
votes

Comment tester la même assertion pour une grande quantité de données

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.

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?

Toute suggestion serait géniale. xxx


2 commentaires

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.


7 Réponses :


2
votes

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 0 , mais vous Je ne sais pas que tant que vous déboguez). D'autre part, répéter self.assertequal (i, 33) est une idée encore pire, car elle introduit la duplication de code.

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

de cette façon, lorsque l'affirmation échoue à 0 , vous le voyez immédiatement sur la trace de la pile imprimée par le module unittest .


2 commentaires

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.



5
votes

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.


0 commentaires

11
votes

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


0 commentaires

2
votes

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


0 commentaires

4
votes

the ddt bibliothèque a été construit pour résoudre exactement ce que vous demandez Unittest [*].

Par exemple: xxx

et lorsque vous l'exécutez, vous obtenez 4 tests au lieu d'une seule: xxx

avis que ddt essaie de proposer des noms pour les TC générés.

Installez-le avec PIP: xxx

[*] La même solution pour le cadre Pythonic Pytest Framework ( Pytest.mark.Parametrizetrize ) est intégré à l'outil Core, et vaut la peine de passer à Pytest juste pour cette fonctionnalité seule.


0 commentaires

0
votes

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 create_a code> et cotisation_b code> que je veux personnaliser.

L'exigence est d'exécuter les deux tests avec la même personnalisation. P>

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)


0 commentaires

5
votes

AS de Python 3.4 Vous pouvez 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.

Voici votre exemple modifié pour utiliser 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)


1 commentaires

Cette réponse est exactement ce que l'OP (et i) nécessaire avec des réécrites minimes.