Reputation: 1857
I'm currently implementing some unit tests for my company's build scripts. To eliminate bloat and make it a little easier to implement new tests, I'm making all my test classes inherit from a custom subclass called BasicTest
that inherits from PyUnit's TestCase.
There are currently two functions that all tests utilize from BasicTest
: The constructor (Although it could obviously be overwritten in the future) and the runTest()
method that is the default method name that the super's constructor uses if no value is passed in (e.g. BasicTest()
would create a test that will execute the runTest()
method when called upon, whereas BasicTest('Foo')
would use the Foo()
method).
I would like to make runTest()
simply run all possible tests from the inheriting object it is called on. However, as runTest()
is defined only in BasicTest
and inherited by the subclasses, I'm looking for a way to dynamically call all of the subclass' methods from the super. I know this violates the rules of OO programming, but from what I can see, Python was never one to follow rules in the first place :)
For clarity, the following illustrates my intentions:
I want runTest()
to be called from a subclass object and only handle that object's methods. Let's say SubclassTest()
that has methods TestParse()
and TestExec()
. I want it so that:
sub = SubClassTest()
sub.runTest()
runs TestParse()
and TestExec()
, but I want the runTest()
method to be defined in and inherited from BasicTest
without being overriden.
Upvotes: 1
Views: 1037
Reputation: 347
Sample code: load base class .py file as module and inspect
import inspect
import imp
imp.load_source((name of class by which to want that module), (path base class name of file).py)
module = __import__((name of class by which to want that module))
inspect.getmembers(module) will give you dict of name, cls
Hope this helps
Upvotes: 1
Reputation: 4182
one can create metaclass which will collect all interesting methods of subclasses into class property
class TestMetaclass(type):
def __new__(cls, name, bases, attrs):
own_tests = [v for k,v in attrs.iteritems() if k.startswith('test')]
attrs['test_method_list'] = own_tests
return super(TestMetaclass, cls).__new__(cls, name, bases, attrs)
set this metaclass to base class as __metaclass__
and implement runTests
method
class BaseTest():
test_method_list = []
__metaclass__ = TestMetaclass
def runTests(self):
for method in self.test_method_list:
method(self)
And after this all subclasses will be constructed using this metaclass
class TestOne(BaseTest):
def test_foo(self):
pass
In the end one can use collected methods running runTests()
method
TestOne().runTests()
Upvotes: 3