"""Generic (non-gomill-specific) test framework code.""" import sys if sys.version_info >= (2, 7): import unittest as unittest2 else: try: import unittest2 except ImportError, e: e.unittest2_missing = True raise # This makes TestResult ignore lines from this module in tracebacks __unittest = True class SupporterError(StandardError): """Exception raised by support objects when something goes wrong. This is raised to indicate things like sequencing errors detected by mock objects. """ class FrameworkTestCase(unittest2.TestCase): """unittest2-style TestCase implementation with a few tweaks.""" # This is default in unittest2 but not python 2.7 unittest, so force it on. longMessage = True def assertItemsEqual(self, expected_seq, actual_seq, msg=None): """Variant implementation of standard assertItemsEqual. This uses the unorderable_list_difference check even if the lists are sortable: I prefer its output. """ expected = list(expected_seq) actual = list(actual_seq) missing, unexpected = unittest2.util.unorderable_list_difference( expected, actual, ignore_duplicate=False ) errors = [] if missing: errors.append('Expected, but missing:\n %s' % unittest2.util.safe_repr(missing)) if unexpected: errors.append('Unexpected, but present:\n %s' % unittest2.util.safe_repr(unexpected)) if errors: standardMsg = '\n'.join(errors) self.fail(self._formatMessage(msg, standardMsg)) class SimpleTestCase(FrameworkTestCase): """TestCase which runs a single function. Instantiate with the test function, which takes a TestCase parameter, eg: def test_xxx(tc): tc.assertEqual(2+2, 4) """ def __init__(self, fn): FrameworkTestCase.__init__(self) self.fn = fn try: self.name = fn.__module__.split(".", 1)[-1] + "." + fn.__name__ except AttributeError: self.name = str(fn) def runTest(self): self.fn(self) def id(self): return self.name def shortDescription(self): return None def __str__(self): return self.name def __repr__(self): return "" % self.name class ParameterisedTestCase(FrameworkTestCase): """Parameterised testcase. Subclasses should define: test_name -- short string parameter_names -- list of identifiers runTest """ def __init__(self, code, *parameters): FrameworkTestCase.__init__(self) self.code = code self.name = "%s.%s:%s" % (self.__class__.__module__.split(".", 1)[-1], self.test_name, code) for name, value in zip(self.parameter_names, parameters): setattr(self, name, value) def runTest(self): raise NotImplementedError def id(self): return self.name def shortDescription(self): return None def __str__(self): return self.name def __repr__(self): return "<%s: %s>" % (self.__class__.__name__, self.name) def _function_sort_key(fn): try: return fn.__code__.co_firstlineno except AttributeError: return str(fn) def make_simple_tests(source, prefix="test_", testcase_class=SimpleTestCase): """Make test cases from a module's test_xxx functions. source -- dict (usually a module's globals()). prefix -- string (default "test_") testcase_class -- SimpleTestCase subclass to use Returns a list of TestCase objects. This makes a TestCase for each function in the values of 'source' whose name begins with 'prefix'. The list is in the order of function definition (using the line number attribute). """ functions = [value for name, value in source.iteritems() if name.startswith(prefix) and callable(value)] functions.sort(key=_function_sort_key) return [testcase_class(fn) for fn in functions] class Fixture(object): """A testing fixture. Instantiate fixture objects with a TestCase parameter. The fixture arranges for any necessary cleanup to be performed by calling TestCase.addCleanUp. """