4

Je reçois des tests d'intégration en cours d'exécution contre la base de données, et je voudrais avoir une structure qui ressemble à quelque chose comme ceci:Comment puis-je obtenir le nez pour trouver les attributs de classe définis sur une classe de test de base?

class OracleMixin(object): 
    oracle = True 
    # ... set up the oracle connection 

class SqlServerMixin(object): 
    sql_server = True 
    # ... set up the sql server connection 

class SomeTests(object): 
    integration = True 
    # ... define test methods here 

class test_OracleSomeTests(SomeTests, OracleMixin): 
    pass 

class test_SqlServerSomeTests(SomeTests, SqlServerMixin): 
    pass 

De cette façon, je peux exécuter des tests SQL Server et teste Oracle séparément comme ceci:

nosetests -a oracle 
nosetests -a sql_server 

Ou tous les tests d'intégration comme celui-ci:

nosetests -a integration 

Cependant, il semble que le nez ne chercher attrib utes sur la sous-classe, pas sur la classe de base. Ainsi, je dois définir les classes de test comme celui-ci ou les essais ne courrai pas:

class test_OracleSomeTests(SomeTests, OracleMixin): 
    oracle = True 
    integration = True 

class test_SqlServerSomeTests(SomeTests, SqlServerMixin): 
    sql_server = True 
    integration = True 

C'est un peu fastidieuse à maintenir. Des idées sur la façon de contourner cela? Si je ne faisais que traiter une classe de base, j'utiliserais simplement une métaclasse et définirais les attributs de chaque classe. Mais j'ai l'impression d'avoir une métaclasse pour la classe de test, une métaclasse pour Oracle et une métaclasse pour SQL Server.

Répondre

4

Je ne pense pas que vous pouvez sans faire votre propre plugin. Le code dans le plugin attrib ne regarde que les classes __dict__. Voici le code

def wantClass(self, cls): 
    """Accept the class if the class or any method is wanted. 
    """ 
    cls_attr = cls.__dict__ 
    if self.validateAttrib(cls_attr) is not False: 
     return None 
    ... 

Vous pouvez pirater le plug-in pour faire quelque chose comme (non testé).

def wantClass(self, cls): 
    """Accept the class if the class or any method is wanted. 
    """ 
    for class_ in cls.__mro__: 
     cls_attr = class_.__dict__ 
     if self.validateAttrib(cls_attr) is not False: 
      return None 
    cls_attr = cls.__dict__ 
    ... 

Cependant, je ne suis pas sûr que cela soit meilleur ou pire que l'option métaclasse.

+0

Si l'une de vos classes parentes sont pas de classes "new-style" (c'est-à-dire qu'elles ne développent pas "object"), je ne pense pas qu'il y aura un attribut '__mro__'. Juste un petit tweak, mais changez la ligne 'pour class_ ...' à 'pour class_ dans getattr (cls, '__mro__', []):' –

0

Si vous voulez trouver un attribut défini sur une classe parente, et vous avez un attribut du même nom dans la sous-classe, vous devrez ajouter le nom de la classe parent pour accéder à la portée que vous voulez

Je crois que c'est ce que vous voulez:

class Parent: 
    prop = 'a property' 

    def self_prop(self): 
     print self.prop 

    # will always print 'a property' 
    def parent_prop(self): 
     print Parent.prop 

class Child(Parent): 
    prop = 'child property' 

    def access_eclipsed(self): 
     print Parent.prop 

class Other(Child): 
    pass 

>>> Parent().self_prop() 
"a property" 
>>> Parent().parent_prop() 
"a property" 
>>> Child().self_prop() 
"child property" 
>>> Child().parent_prop() 
"a property" 
>>> Child().access_eclipsed() 
"a property" 
>>> Other().self_prop() 
"child property" 
>>> Other().parent_prop() 
"a property" 
>>> Other().access_eclipsed() 
"a property" 

et dans votre cas, il semble que vous avez deux classes différentes qui définissent différentes variables de sorte que vous pouvez juste avoir un essai: catch: en haut de vos fonctions de test ou peut-être dans l'initialiseur

et dire

try: 
    isSQLServer = self.sql_server 
except AttributeError: 
    isSQLServer = False 

(si vraiment ils devraient définirez les mêmes variables afin que la classe de test ne pas savoir quoi que ce soit sur les sous-classes)