我刚把我的课程转换成了一个“自我注册”类。这是我第一次尝试巨蟒元类。奇怪的是,许多通过的测试开始以奇怪的方式失败。这些失败的测试中有许多在自己运行时会通过,而不是作为套件的一部分运行。这使我相信,测试之间存在某种“数据出血”。所以我做了一些测试来确定这是否是真的,我是对的。
现在的问题是,我该如何解决这个问题。带有del()的tearDown()方法不起作用。添加一个下降卡车(del(self))不起作用。如何从_registry中注销项目,使它们不会交叉污染其他测试?
有趣的是,下面的第一个测试通过了,直到我添加了第二个测试。
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 ])发布于 2014-04-30 00:42:08
我不认为在这种情况下你需要一个超能力。
class foo(object):
_registry = []
def __init__(self, name):
self._registry.append(self)
self.name = name为什么不直接在_registry上迭代呢?至于删除x2,foo._registry并不比names少;所以使用.remove方法。
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 ])发布于 2014-04-30 00:57:25
为什么要显式地使用类名而不是self?例如:
x1 = TEST_IterateRegister_instantiation.foo(names[0])
x2 = TEST_IterateRegister_instantiation.foo(names[1])
x3 = TEST_IterateRegister_instantiation.foo(names[2])而不是:
x1 = self.foo(names[0])
x2 = self.foo(names[1])
x3 = self.foo(names[2])此外,我不认为del正在做您认为它所做的事情。del所做的一切都是remove a bound identifier from the namespace,所以:
del(x2)相当于编写x2 = None,而这并不是您想要做的。没有析构函数。字符串是不可变的,对其进行更改不会改变names。
在回答您的问题时,听起来您的问题是_registry是可变的,所以对cls._registry的更改对所有子类都是可见的。解决这一问题的最简单方法是使用设置IterateRegister._registry = []的teardown方法。但是,我认为您应该重新考虑这个解决方案:如果它已经在IterateRegister保持状态的测试中造成了问题,那么在生产代码中跟踪不太容易吗?
https://stackoverflow.com/questions/23373979
复制相似问题