4

Ich erhalte einige Tests Integration mit der Datenbank ausgeführt wird, und ich möchte eine Struktur haben, die etwa wie folgt aussieht:Wie bekomme ich die Nase nach Klassenattributen, die in einer Basistestklasse definiert sind?

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 

Auf diese Weise ich SQL Server Tests ausführen kann und Oracle-Tests separat wie dies:

nosetests -a oracle 
nosetests -a sql_server 

oder alle Integrationstests wie folgt aus:

nosetests -a integration 

Allerdings scheint es, dass die Nase für attrib nur aussehen utes auf der Unterklasse, nicht auf der Basisklasse. So muss ich so die Testklassen definieren oder die Tests werden nicht ausgeführt:

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

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

Dies ist ein bisschen langweilig zu halten. Irgendwelche Ideen, wie man das umgehen kann? Wenn ich nur mit einer Basisklasse beschäftigt wäre, würde ich einfach eine Metaklasse verwenden und die Attribute für jede Klasse definieren. Aber ich habe ein unbehagliches Gefühl, eine Metaklasse für die Testklasse, eine Metaklasse für Oracle und eine Metaklasse für SQL Server zu haben.

Antwort

4

Ich glaube nicht, dass Sie ohne ein eigenes Plugin machen können. Der Code im Attrib-Plugin betrachtet nur die Klassen __dict__. Hier ist die 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 
    ... 

Sie können das Plug-Hack zu tun, so etwas wie (nicht getestet).

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__ 
    ... 

aber ich bin nicht sicher, dass dies besser oder schlechter ist, dass die Metaklasse Option.

+0

Wenn einer Ihrer Eltern-Klassen sind nicht "New-Style" -Klassen (das heißt, sie erweitern "Objekt" nicht), ich glaube nicht, dass es ein "__mro__" -Attribut geben wird. Nur eine kleine zwicken, aber ändern Sie die Zeile 'für Klasse_ ...' zu 'für Klasse_ in getattr (cls, '__mro__', []):' –

0

Wenn Sie ein Attribut zu finden, auf einer übergeordneten Klasse definiert sind, und Sie haben ein Attribut mit dem gleichen Namen in der Unterklasse müssen Sie den Namen der Elternklasse hinzufügen, um den Bereich, den Sie

zugreifen möchten ich glaube, das ist, was Sie wollen:

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" 

und in Ihrem Fall sieht es aus wie Sie zwei verschiedene Klassen haben, die unterschiedlichen Variablen definieren, so dass Sie nur einen Versuch haben: Fang: an der Spitze des Testfunktion oder vielleicht in der Initialisierung

und sagen

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

(obwohl eigentlich sollten sie die gleichen Variablen definieren, so dass die Testklasse nichts über die Unterklassen zu wissen hat)