Reputation: 3100
I have my nice base test class which extends from the django test case and another class:
class MyTestCase(TestCase, TestFreshProvisionedEachTest):
Now it all works nicely, except that to make it work we have to patch (with Foord's mock library) a couple of functions in the middleware.
My idea is that this would have worked fine:
@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):
However it doesn't seem to work, the methods of the subclass are not patched. I thought then that there could be a way to do something like
MyTestCase = patch(MyTestCase, 'spotlight.middleware.extract_host_name', new=lambda host_name: TEST_DOMAIN)
But that also is not possible.
Is there a way to avoid this repetition and do a patch on a superclass which patches all the subclasses methods as well?
Upvotes: 2
Views: 738
Reputation: 1101
It's better to use a metaclass for that, as it makes easier to handle inheritance of test cases, than manually applying decorators. Something along these lines (I haven't tested it, but you should get the idea):
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):
...
With this approach all methods of all subclasses of PatchedTestCase
will be patched. You can also define other base classes with different patch_method
implementations.
Upvotes: 1