[英]Python How to call child class method from Parent metaclass
I am trying to write my own implementation of test runner, what I struggle with is some kind of setUp and TearDown methods and how to override/invoke them.我正在尝试编写自己的测试运行器实现,我遇到的是某种 setUp 和 TearDown 方法以及如何覆盖/调用它们。
class MetaTestCase(type):
def __call__(self, *args, **kwds):
return super().__call__(*args, **kwds)
def __new__(self, name, bases, attrs):
def replaced_fnc(fn):
def new_test(*args, **kwargs):
self.before(self)
result = fn(*args, **kwargs)
self.after(self)
return result
return new_test
for i in attrs:
if callable(attrs[i]):
attrs[i] = replaced_fnc(attrs[i])
return (super(MetaTestCase, self).__new__(self, name, bases, attrs))
def before(self):
print('Before')
def after(self):
print('After')
class TestCase(metaclass=MetaTestCase):
pass
class TestSuite(TestCase):
def before(self):
print('New Before')
def after(self):
print('New After')
def test(self):
print("Test")
if __name__ == "__main__":
TS = TestSuite()
TS.test()
The current output of that is:当前的 output 是:
Before
Test
After
But the expected output would be to override those functions from metaclass with those from Child Class like that:但是预期的 output 将使用来自子类 Class 的函数覆盖元类中的这些函数,如下所示:
New Before
Test
New After
But I don't really know metaclasses very good and how to pass Child methods to the Parent class.但我真的不太了解元类以及如何将子方法传递给父 class。
Like chepner suggest u don't need a metaclass for this.就像 chepner 建议你不需要一个元类。 Define a test runner that takes the suite TS as an argument, and it just calls TS.before, TS.test, and TS.after explicitly and in sequence.定义一个将套件 TS 作为参数的测试运行器,它只是显式地依次调用 TS.before、TS.test 和 TS.after。
I just answer to question, how to call extra method from metaclass我只是回答问题,如何从元类中调用额外的方法
Here u can read more aboute metaclasses . 在这里你可以阅读更多关于元类的信息。 But quick answer will be, just use polymorphism.但快速的答案是,只需使用多态性。
So first of all u need to move your before and after method to parent class(not metaclass).所以首先你需要将你的前后方法移动到父类(而不是元类)。 In python when we work with objects, first argument is always self so we can use that like: args[0].before()在 python 中,当我们使用对象时,第一个参数始终是 self 所以我们可以像这样使用:args[0].before()
Next problem is infinite loop.下一个问题是无限循环。 We need to decied which function we need to overwrite in meta class, in my answaer I simple check if method name contain 'test', but u can create smth more sophisticated我们需要确定我们需要在元 class 中覆盖哪个 function,在我的回答中,我简单检查方法名称是否包含“测试”,但您可以创建更复杂的
class MetaTestCase(type):
def __call__(self, *args, **kwds):
return super().__call__(*args, **kwds)
def __new__(self, name, bases, attrs):
def replaced_fnc(fn):
def new_test(*args, **kwargs):
args[0].before()
result = fn(*args, **kwargs)
args[0].after()
return result
return new_test
for i in attrs:
if callable(attrs[i]) and 'test' in attrs[i].__name__:
attrs[i] = replaced_fnc(attrs[i])
return (super(MetaTestCase, self).__new__(self, name, bases, attrs))
class TestCase(metaclass=MetaTestCase):
def before(self):
print('Before')
def after(self):
print('After')
class TestSuite(TestCase):
def before(self):
print('New Before')
def after(self):
print('New After')
def test(self):
print("Test")
if __name__ == "__main__":
TS = TestSuite()
TS.test()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.