##Test Reuse via Multiple Inheritance This pattern allows reuse of the same set of "core" tests across many concrete implementations of a class hierarchy. The tests can be written to test core functionality while concrete test classes provide specifics geared towards each concrete implementation. In conjunction with the get_props decorator, this pattern can provide a very high degree of test reuse (resulting in increased test coverage) without sacrificing the specificity for concrete implementations. Addition of new concrete tests gets the benefit of all of the base tests with only a relatively small amount of property configuration.
##get_props Decorator Evaluates the contents of TESTING_PROPERTIES on a test-by-test basis and Provides a self.method_name.props attribute to the method that contains a dictionary of properties
The TESTING_PROPERTIES dictionary can be extended/amended by subclasses to provide specific properties on a class-wide and/or test-by-test basis
The TESTING_PROPERTIES dict should be deepcopied in each subclass and the keys overridden as necessary
All 'top level' values MUST be instances of dict
Keys overridden by subclasses are done so in a 'non-destructive' manner. In the example below, any keys present in the BaseTest.TESTING_PROPERTIES['defaults'] dictionary OTHER than 'time_steps' will be preserved.
The properties available to a specific test are a non-destructive combination of 'defaults' and those for the specific test.
Subclass Example - see testing_inheritance.py for more:
from copy import deepcopy
TESTING_PROPERTIES = deepcopy(BaseTest.TESTING_PROPERTIES
TESTING_PROPERTIES['defaults'] = {'time_steps': 20}
TESTING_PROPERTIES['test_method_one'] = {'my_prop': 'myval'}
@get_props()
def test_method_one(self):
props = self.test_method_one.props
time_steps = props['time_steps']
assert time_steps == 20
myprop = props['my_prop']
assert myprop == 'myval'
##Running testing_inheritance.py
The other file in this gist, testing_inheritance.py, showcases both the inheritance pattern and the get_props decorator. It requires nose to be installed (pip install nose)
Run with the -vs flags to show descriptive output on how the inheritance pattern and get_props decorator work:
nosetests testing_inheritance -vs