196 votes

Python unité de test avec base et la sous catégorie

J'ai actuellement quelques tests unitaires qui partagent un ensemble de tests. Voici un exemple:

import unittest

class BaseTest(unittest.TestCase):

    def testCommon(self):
        print 'Calling BaseTest:testCommon'
        value = 5
        self.assertEquals(value, 5)

class SubTest1(BaseTest):

    def testSub1(self):
        print 'Calling SubTest1:testSub1'
        sub = 3
        self.assertEquals(sub, 3)


class SubTest2(BaseTest):

    def testSub2(self):
        print 'Calling SubTest2:testSub2'
        sub = 4
        self.assertEquals(sub, 4)

if __name__ == '__main__':
    unittest.main()

La sortie de la ci-dessus est:

Calling BaseTest:testCommon
.Calling BaseTest:testCommon
.Calling SubTest1:testSub1
.Calling BaseTest:testCommon
.Calling SubTest2:testSub2
.
----------------------------------------------------------------------
Ran 5 tests in 0.000s

OK

Est-il un moyen de réécrire le ci-dessus de sorte que la première testCommon n'est pas appelé?

EDIT: Au lieu de courir 5 tests ci-dessus, je veux le lancer 4 essais, 2 de l'SubTest1 et un autre 2 à partir de SubTest2. Il semble que Python unittest est l'exécution de l'original BaseTest sur son propre et j'ai besoin d'un mécanisme pour empêcher que cela se produise.

168voto

Matthew Marshall Points 2521

L'utilisation de l'héritage multiple, de sorte que votre classe avec des tests communs n'est pas elle-même hérite de cas de test.

import unittest

class CommonTests(object):
    def testCommon(self):
        print 'Calling BaseTest:testCommon'
        value = 5
        self.assertEquals(value, 5)

class SubTest1(unittest.TestCase, CommonTests):

    def testSub1(self):
        print 'Calling SubTest1:testSub1'
        sub = 3
        self.assertEquals(sub, 3)


class SubTest2(unittest.TestCase, CommonTests):

    def testSub2(self):
        print 'Calling SubTest2:testSub2'
        sub = 4
        self.assertEquals(sub, 4)

if __name__ == '__main__':
    unittest.main()

40voto

Wojciech B. Points 21

Vous pouvez résoudre ce problème avec une seule commande:

del(BaseTest)

Ainsi, le code ressemblera à ceci:

import unittest

class BaseTest(unittest.TestCase):

    def testCommon(self):
        print 'Calling BaseTest:testCommon'
        value = 5
        self.assertEquals(value, 5)

class SubTest1(BaseTest):

    def testSub1(self):
        print 'Calling SubTest1:testSub1'
        sub = 3
        self.assertEquals(sub, 3)


class SubTest2(BaseTest):

    def testSub2(self):
        print 'Calling SubTest2:testSub2'
        sub = 4
        self.assertEquals(sub, 4)

del(BaseTest)

if __name__ == '__main__':
    unittest.main()

38voto

Denis Golomazov Points 1211

Matthew Marshall réponse est grande, mais il exige que vous héritez de deux classes dans chacun de vos cas de test, qui est sujette à erreur. Au lieu de cela, j'utilise ce (python>=2.7):

class BaseTest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        if cls is BaseTest:
            raise unittest.SkipTest("Skip BaseTest tests, it's a base class")
        super(BaseTest, cls).setUpClass()

9voto

John Millikin Points 86775

Qu'essayez-vous de réaliser? Si vous avez le bon code de test (assertions, modèle de tests, etc), puis les placer dans des méthodes qui ne sont pas avec le préfixe test donc unittest ne se charge pas.

import unittest

class CommonTests(unittest.TestCase):
      def common_assertion(self, foo, bar, baz):
          # whatever common code
          self.assertEqual(foo(bar), baz)

class BaseTest(CommonTests):

    def testCommon(self):
        print 'Calling BaseTest:testCommon'
        value = 5
        self.assertEquals(value, 5)

class SubTest1(CommonTests):

    def testSub1(self):
        print 'Calling SubTest1:testSub1'
        sub = 3
        self.assertEquals(sub, 3)

class SubTest2(CommonTests):

    def testSub2(self):
        print 'Calling SubTest2:testSub2'
        sub = 4
        self.assertEquals(sub, 4)

if __name__ == '__main__':
    unittest.main()

7voto

Jason A Points 158

Matthew est la réponse dont j'avais besoin pour l'utiliser depuis que je suis sur de 2,5 encore. Mais que de 2,7 vous pouvez utiliser le @unittest.skip() décorateur sur toutes les méthodes de test que vous souhaitez ignorer.

http://docs.python.org/library/unittest.html#skipping-tests-and-expected-failures

Vous aurez besoin de mettre en place votre propre saut décorateur pour vérifier le type de base. N'avez pas utilisé cette fonctionnalité avant, mais du haut de ma tête que vous pourriez utiliser BaseTest comme un marqueur de type à condition de les ignorer:

def skipBaseTest(obj):
    if type(obj) is BaseTest:
        return unittest.skip("BaseTest tests skipped")
    return lambda func: func

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X