我有很好的基础测试类,它从 django 测试用例和另一个类扩展而来:
class MyTestCase(TestCase, TestFreshProvisionedEachTest):
现在一切正常,只是为了让它正常工作,我们必须(使用 Foord 的模拟库)修补中间件中的几个函数。
我的想法是这会工作得很好:
@patch('spotlight.middleware.extract_host_name', new=lambda host_name:
TEST_DOMAIN)
@patch('spotlight.middleware.extract_host_key', new=lambda host_key:
company_name_to_db(TEST_DOMAIN))
class MyTestCase(TestCase, TestFreshProvisionedEachTest):
不过好像不行,子类的方法没有打补丁。 我当时想可能有一种方法可以做类似的事情
MyTestCase = patch(MyTestCase, 'spotlight.middleware.extract_host_name', new=lambda host_name: TEST_DOMAIN)
但这也是不可能的。
有没有办法避免这种重复并在父类(super class)上打补丁 哪个也修补所有子类方法?
请您参考如下方法:
最好为此使用元类,因为它比手动应用装饰器更容易处理测试用例的继承。类似这些(我还没有测试过,但你应该明白了):
class TestMeta(type(TestCase)):
def patch_method(cls, meth):
raise NotImplementedError
def __new__(mcls, name, bases, dct):
to_patch = []
for methname, meth in dct.items():
if methname.startswith('test') and callable(meth):
to_patch.append(methname)
cls = super().__new__(mcls, name, bases, dct)
for methname in to_patch:
meth = getattr(cls, methname)
meth = cls.patch_method(meth)
setattr(cls, methname, meth)
return cls
class PatchedTestCase(TestCase, metaclass=TestMeta):
@classmethod
def patch_method(cls, meth):
meth = patch('spotlight.middleware.extract_host_name',
new=lambda host_name: TEST_DOMAIN)(meth)
meth = patch('spotlight.middleware.extract_host_key',
new=lambda host_key: company_name_to_db(TEST_DOMAIN))(meth)
return meth
class MyTestCase(PatchedTestCase, TestFreshProvisionedEachTest):
...
通过这种方法,PatchedTestCase 的所有子类的所有方法都将被修补。您还可以使用不同的 patch_method 实现定义其他基类。
