如何让nose查找基类测试类中定义的类属性?

4 投票
2 回答
1471 浏览
提问于 2025-04-15 13:12

我正在进行一些针对数据库的集成测试,我希望有一个像这样的结构:

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

这样,我就可以分别运行SQL Server的测试和Oracle的测试,方法是:

nosetests -a oracle
nosetests -a sql_server

或者可以这样运行所有的集成测试:

nosetests -a integration

不过,看起来nose只会查找子类上的属性,而不会查找基类上的属性。因此,我必须这样定义测试类,否则测试就无法运行:

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

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

这样维护起来有点麻烦。有没有什么办法可以解决这个问题?如果我只处理一个基类,我可以使用元类并在每个类上定义属性。但是我对为测试类、Oracle和SQL Server各自使用一个元类这件事有点不安。

2 个回答

0

如果你想找到一个在父类中定义的属性,而在子类中有一个同名的属性,你需要加上父类的名字来访问你想要的那个属性。

我觉得这就是你想要的:

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"

在你的情况下,看起来你有两个不同的类,它们定义了不同的变量,所以你可以在你的测试函数的开头或者初始化的时候加一个尝试:捕获:的结构。

然后说

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

(不过其实它们应该定义相同的变量,这样测试类就不需要了解子类的任何信息了)

4

我觉得你可能需要自己写一个插件,因为现有的attrib插件里的代码只关注类的__dict__。这里有个代码

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

你可以尝试修改这个插件,做一些类似的事情(不过我没有测试过)。

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

不过,我不确定这样做到底比使用元类的方式好还是不好。

撰写回答