我怎样才能找到在基本测试类上定义的类属性?

发布于 2024-07-27 22:31:16 字数 1054 浏览 16 评论 0原文

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

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 的元类,我感到不安。

I'm getting some integration tests running against the database, and I'd like to have a structure that looks something like this:

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

This way, I can run SQL Server tests and Oracle tests separately like this:

nosetests -a oracle
nosetests -a sql_server

Or all integration tests like this:

nosetests -a integration

However, it appears that nose will only look for attributes on the subclass, not on the base class. Thus I have to define the test classes like this or the tests won't run:

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

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

This is a bit tedious to maintain. Any ideas how to get around this? If I was just dealing with one base class, I'd just use a metaclass and define the attributes on each class. But I get an uneasy feeling about having a metaclass for the test class, a metaclass for Oracle, and a metaclass for SQL Server.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦一生花开无言 2024-08-03 22:31:16

我认为如果不制作自己的插件就无法做到这一点。 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__
    ...

但是,我不确定这比元类选项是好是坏。

I do not think you can without making your own plugin. The the code in the attrib plugin only looks at the classes __dict__. Here is the 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
    ...

You could hack the plugin to do something like (not tested).

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

However, I am not sure that this is better or worse that the metaclass option.

寄风 2024-08-03 22:31:16

如果您想查找在父类上定义的属性,并且子类中有一个同名的属性,您将需要添加父类的名称才能访问您想要的范围

我相信这就是什么你想要:

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"

,在你的情况下,看起来你有两个不同的类,它们定义了不同的变量,所以你可以在测试函数的顶部或者在初始化器

中进行尝试:catch:并说

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

(尽管实际上他们应该定义相同的变量,以便测试类不必了解有关子类的任何信息)

If you want to find an attribute defined on a parent class, and you have an attribute of the same name in the subclass you will need to add the name of the parent class to access the scope you want

I believe this is what you want:

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"

and in your case it looks like you have two different classes which define different variables so you can just have a try: catch: at the top of your test functions or maybe in the initializer

and say

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

(though really they should be defining the same variables so that the test class doesn't have to know anything about the subclasses)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文