首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python单元测试和自注册类

Python单元测试和自注册类
EN

Stack Overflow用户
提问于 2014-04-29 19:50:24
回答 2查看 191关注 0票数 0

我刚把我的课程转换成了一个“自我注册”类。这是我第一次尝试巨蟒元类。奇怪的是,许多通过的测试开始以奇怪的方式失败。这些失败的测试中有许多在自己运行时会通过,而不是作为套件的一部分运行。这使我相信,测试之间存在某种“数据出血”。所以我做了一些测试来确定这是否是真的,我是对的。

现在的问题是,我该如何解决这个问题。带有del()的tearDown()方法不起作用。添加一个下降卡车(del(self))不起作用。如何从_registry中注销项目,使它们不会交叉污染其他测试?

有趣的是,下面的第一个测试通过了,直到我添加了第二个测试。

代码语言:javascript
复制
class IterateRegister(type):
    def __iter__(cls):
        return iter(cls._registry)

class TEST_IterateRegister_instantiation(unittest.TestCase):
    class foo(metaclass=IterateRegister):
        _registry = []

        def __init__(self, name):
            self._registry.append(self)
            self.name = name

    def test__iterate_register_metaclass(self):
        names = ['Shaggy', 'Scooby', 'Snack']

        x1 = TEST_IterateRegister_instantiation.foo(names[0])
        x2 = TEST_IterateRegister_instantiation.foo(names[1])
        x3 = TEST_IterateRegister_instantiation.foo(names[2])

        self.assertEqual(names, [ f.name for f in TEST_IterateRegister_instantiation.foo ])

    def test__destruction_deletes_class_from_registry(self):
        names = ['Shaggy', 'Scooby', 'Snack']

        x1 = TEST_IterateRegister_instantiation.foo(names[0])
        x2 = TEST_IterateRegister_instantiation.foo(names[1])
        x3 = TEST_IterateRegister_instantiation.foo(names[2])

        del(x2)
        names.remove('Scooby')

        self.assertEqual(names, [ f.name for f in TEST_IterateRegister_instantiation.foo ])
EN

回答 2

Stack Overflow用户

发布于 2014-04-30 00:42:08

我不认为在这种情况下你需要一个超能力。

代码语言:javascript
复制
class foo(object):
    _registry = []

    def __init__(self, name):
        self._registry.append(self)
        self.name = name

为什么不直接在_registry上迭代呢?至于删除x2foo._registry并不比names少;所以使用.remove方法。

代码语言:javascript
复制
def test__destruction_deletes_class_from_registry(self):
    names = ['Shaggy', 'Scooby', 'Snack']

    x1 = self.foo(names[0])
    x2 = self.foo(names[1])
    x3 = self.foo(names[2])

    foo._registry.remove(x2)
    names.remove('Scooby')

    self.assertEqual(names, [ f.name for f in self.foo._registry ])
票数 1
EN

Stack Overflow用户

发布于 2014-04-30 00:57:25

为什么要显式地使用类名而不是self?例如:

代码语言:javascript
复制
x1 = TEST_IterateRegister_instantiation.foo(names[0])
x2 = TEST_IterateRegister_instantiation.foo(names[1])
x3 = TEST_IterateRegister_instantiation.foo(names[2])

而不是:

代码语言:javascript
复制
x1 = self.foo(names[0])
x2 = self.foo(names[1])
x3 = self.foo(names[2])

此外,我不认为del正在做您认为它所做的事情。del所做的一切都是remove a bound identifier from the namespace,所以:

代码语言:javascript
复制
del(x2)

相当于编写x2 = None,而这并不是您想要做的。没有析构函数。字符串是不可变的,对其进行更改不会改变names

在回答您的问题时,听起来您的问题是_registry是可变的,所以对cls._registry的更改对所有子类都是可见的。解决这一问题的最简单方法是使用设置IterateRegister._registry = []的teardown方法。但是,我认为您应该重新考虑这个解决方案:如果它已经在IterateRegister保持状态的测试中造成了问题,那么在生产代码中跟踪不太容易吗?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23373979

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档