SwarthyMantooth
SwarthyMantooth

Reputation: 1857

Call all subclass methods from super?

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

Answers (2)

Manuj Rastogi
Manuj Rastogi

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

oleg
oleg

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

Related Questions