J'ai actuellement quelques tests unitaires qui partagent un ensemble commun 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()
Le résultat de ce qui précède est:
Calling BaseTest:testCommon
.Calling BaseTest:testCommon
.Calling SubTest1:testSub1
.Calling BaseTest:testCommon
.Calling SubTest2:testSub2
.
----------------------------------------------------------------------
Ran 5 tests in 0.000s
OK
Existe-t-il un moyen de réécrire ce qui précède afin que le tout premier testCommon
ne soit pas appelé?
EDIT: au lieu d'exécuter 5 tests ci-dessus, je veux qu'il n'exécute que 4 tests, 2 du SubTest1 et 2 autres de SubTest2. Il semble que Python unittest exécute seul le BaseTest d'origine et j'ai besoin d'un mécanisme pour empêcher que cela ne se produise.
python
unit-testing
testing
Thierry Lam
la source
la source
Réponses:
Utilisez l'héritage multiple, de sorte que votre classe avec des tests communs n'hérite pas elle-même de TestCase.
la source
setUp
ettearDown
à laCommonTests
classe, et que vous voulez qu'elles soient appelées pour chaque test dans les classes dérivées, vous devez inverser l'ordre des classes de base, de sorte que ce sera:class SubTest1(CommonTests, unittest.TestCase)
.unittest.TestCase
etCommonTests
. Je pense que lasetUpClass
méthode ci-dessous est la meilleure et qu'elle est moins sujette à l'erreur humaine. Soit cela, soit envelopper la classe BaseTest dans une classe conteneur qui est un peu plus piratée mais évite le message de saut dans l'impression du test.CommonTests
appelle des méthodes qui n'existent pas dans cette classe.N'utilisez pas d'héritage multiple, cela vous mordra plus tard .
Au lieu de cela, vous pouvez simplement déplacer votre classe de base dans le module séparé ou l'envelopper avec la classe vide:
Le résultat:
la source
Vous pouvez résoudre ce problème avec une seule commande:
Donc, le code ressemblerait à ceci:
la source
self.assert*
méthodes n'existent pas dans un objet standard.super( BaseTest, cls ).setUpClass( )
BaseTest
peut être référencé viasuper(self.__class__, self)
ou simplementsuper()
dans les sous-classes, mais apparemment pas si vous héritiez de constructeurs . Peut-être existe-t-il aussi une alternative «anonyme» lorsque la classe de base a besoin de se référencer elle-même (pas que je sache quand une classe doit se référencer elle-même).La réponse de Matthew Marshall est excellente, mais elle nécessite que vous héritiez de deux classes dans chacun de vos cas de test, ce qui est sujet aux erreurs. Au lieu de cela, j'utilise ceci (python> = 2.7):
la source
Qu'essayez-vous d'accomplir? Si vous avez du code de test commun (assertions, tests de modèle, etc.), placez-les dans des méthodes qui ne sont pas préfixées par
test
conséquentunittest
ne les chargeront pas.la source
La réponse de Matthew est celle que j'avais besoin d'utiliser puisque je suis toujours sur 2.5. Mais à partir de 2.7, vous pouvez utiliser le décorateur @ unittest.skip () sur toutes les méthodes de test que vous voulez ignorer.
http://docs.python.org/library/unittest.html#skipping-tests-and-expected-failures
Vous devrez implémenter votre propre décorateur de saut pour vérifier le type de base. Je n'ai jamais utilisé cette fonctionnalité auparavant, mais du haut de ma tête, vous pouvez utiliser BaseTest comme type de marqueur pour conditionner le saut:
la source
J'ai pensé à résoudre ce problème en masquant les méthodes de test si la classe de base est utilisée. De cette façon, les tests ne sont pas ignorés, de sorte que les résultats des tests peuvent être verts au lieu de jaunes dans de nombreux outils de rapport de test.
Par rapport à la méthode mixin, les ide comme PyCharm ne se plaindront pas que les méthodes de test unitaire sont absentes de la classe de base.
Si une classe de base hérite de cette classe, elle devra remplacer les méthodes
setUpClass
ettearDownClass
.la source
Vous pouvez ajouter
__test_ = False
une classe BaseTest, mais si vous l'ajoutez, sachez que vous devez ajouter des__test__ = True
classes dérivées pour pouvoir exécuter des tests.la source
Une autre option est de ne pas exécuter
Au lieu de cela, vous pouvez utiliser
Donc, vous n'exécutez que les tests dans la classe
TestClass
la source
unittest.main()
collecté dans la suite par défaut, vous formez une suite explicite et exécutez ses tests.J'ai fait à peu près la même chose que @Vladim P. ( https://stackoverflow.com/a/25695512/2451329 ) mais légèrement modifié:
et nous y voilà.
la source
Depuis Python 3.2, vous pouvez ajouter une fonction test_loader à un module pour contrôler quels tests (le cas échéant) sont trouvés par le mécanisme de découverte de test.
Par exemple, ce qui suit ne chargera que l'affiche
SubTest1
etSubTest2
les cas de test d'origine, en ignorantBase
:Il devrait être possible d'itérer
standard_tests
(TestSuite
contenant les tests trouvés par le chargeur par défaut) et de copier tout saufBase
verssuite
, mais la nature imbriquée deTestSuite.__iter__
rend cela beaucoup plus compliqué.la source
Renommez simplement la méthode testCommon en quelque chose d'autre. Unittest saute (généralement) tout ce qui ne contient pas de «test».
Rapide et simple
la source
C'est donc une sorte de vieux fil mais je suis tombé sur ce problème aujourd'hui et j'ai pensé à mon propre hack pour cela. Il utilise un décorateur qui rend les valeurs des fonctions None lorsqu'il est accédé via la classe de base. Ne vous inquiétez pas de la configuration et de la classe de configuration car si la classe de base n'a pas de tests, elle ne s'exécutera pas.
la source
Voici une solution qui n'utilise que des fonctionnalités unittest documentées et qui évite d'avoir un statut «skip» dans vos résultats de test:
Comment ça marche: selon la
unittest.TestCase
documentation , "Chaque instance de TestCase exécutera une seule méthode de base: la méthode nommée methodName." Les "runTests" par défaut exécutent toutes les méthodes de test * sur la classe - c'est ainsi que les instances de TestCase fonctionnent normalement. Mais lors de l'exécution dans la classe de base abstraite elle-même, vous pouvez simplement remplacer ce comportement par une méthode qui ne fait rien.Un effet secondaire est que votre nombre de tests augmentera de un: le "test" runNoTestsInBaseClass est compté comme un test réussi lorsqu'il est exécuté sur BaseClass.
(Cela fonctionne également dans Python 2.7, si vous êtes toujours là-dessus. Il suffit de changer
super()
poursuper(BaseTest, self)
.)la source
Changez le nom de la méthode BaseTest en setUp:
Production:
De la documentation :
la source
setUp
?test...
méthode,setUp
est exécutée encore et encore et encore, une fois pour une telle méthode; ce n'est donc PAS une bonne idée d'y mettre des tests!