import sys import unittest from nose_helper.config import Config from nose_helper.util import resolve_name, try_run import imp class Test(unittest.TestCase): """The universal test case wrapper. """ __test__ = False # do not collect def __init__(self, test, config=None): if not hasattr(test, '__call__'): raise TypeError("Test called with argument %r that " "is not callable. A callable is required." % test) self.test = test if config is None: config = Config() self.config = config unittest.TestCase.__init__(self) def __call__(self, *arg, **kwarg): return self.run(*arg, **kwarg) def __str__(self): return str(self.test) def _context(self): try: return self.test.context except AttributeError: pass try: return self.test.__class__ except AttributeError: pass try: return resolve_name(self.test.__module__) except AttributeError: pass return None context = property(_context, None, None, """Get the context object of this test.""") def run(self, result): try: self.runTest(result) except KeyboardInterrupt: raise except: err = sys.exc_info() result.addError(self, err) def runTest(self, result): test = self.test test(result) class TestBase(unittest.TestCase): """Common functionality for FunctionTestCase and MethodTestCase. """ __test__ = False # do not collect class Suite: pass def runTest(self): self.test(*self.arg) class FunctionTestCase(TestBase): """TestCase wrapper for test functions. """ __test__ = False # do not collect def __init__(self, test, setUp=None, tearDown=None, arg=tuple(), descriptor=None): self.test = test self.setUpFunc = setUp self.tearDownFunc = tearDown self.arg = arg self.descriptor = descriptor TestBase.__init__(self) self.suite = TestBase.Suite() self.suite.__module__ = self.__get_module() self.suite.__name__ = "" has_module = True try: imp.find_module(self.suite.__module__)[1] except ImportError: has_module = False if sys.version.find("IronPython") != -1 or not has_module: # Iron Python doesn't fully support imp self.suite.abs_location = "" self.suite.location = "" else: self.suite.abs_location = "file://" + imp.find_module(self.suite.__module__)[1] self.suite.location = "file://" + imp.find_module(self.suite.__module__)[1] def _context(self): return resolve_name(self.test.__module__) context = property(_context, None, None, """Get context (module) of this test""") def setUp(self): """Run any setup function attached to the test function """ if self.setUpFunc: self.setUpFunc() else: names = ('setup', 'setUp', 'setUpFunc') try_run(self.test, names) def tearDown(self): """Run any teardown function attached to the test function """ if self.tearDownFunc: self.tearDownFunc() else: names = ('teardown', 'tearDown', 'tearDownFunc') try_run(self.test, names) def __str__(self): func, arg = self._descriptors() if hasattr(func, 'compat_func_name'): name = func.compat_func_name else: name = func.__name__ if arg: name = "%s%s" % (name, arg) return name __repr__ = __str__ def __get_module(self): func, arg = self._descriptors() if hasattr(func, "__module__"): return func.__module__ else: #TODO[kate]: get module of function in jython < 2.2 return "Unknown module." def _descriptors(self): """In most cases, this is the function itself and no arguments. For tests generated by generator functions, the original (generator) function and args passed to the generated function are returned. """ if self.descriptor: return self.descriptor, self.arg else: return self.test, self.arg class MethodTestCase(TestBase): """Test case wrapper for test methods. """ __test__ = False # do not collect def __init__(self, method, test=None, arg=tuple(), descriptor=None): """Initialize the MethodTestCase. """ self.method = method self.test = test self.arg = arg self.descriptor = descriptor self.cls = method.im_class self.inst = self.cls() if self.test is None: method_name = self.method.__name__ self.test = getattr(self.inst, method_name) TestBase.__init__(self) self.suite = TestBase.Suite() self.suite.__module__, self.suite.__name__ = self.__get_module() has_module = True try: imp.find_module(self.suite.__module__)[1] except ImportError: has_module = False if sys.version.find("IronPython") != -1 or not has_module: # Iron Python doesn't fully support imp self.suite.abs_location = "" else: self.suite.abs_location = "file://" + imp.find_module(self.suite.__module__)[1] self.suite.location = "python_uttestid://" + self.suite.__module__ + "." + self.suite.__name__ def __get_module(self): def get_class_that_defined_method(meth): import inspect obj = meth.im_self for cls in inspect.getmro(meth.im_class): if meth.__name__ in cls.__dict__: return (cls.__module__, cls.__name__) return ("Unknown module", "") func, arg = self._descriptors() return get_class_that_defined_method(func) def __str__(self): func, arg = self._descriptors() if hasattr(func, 'compat_func_name'): name = func.compat_func_name else: name = func.__name__ if arg: name = "%s%s" % (name, arg) return name __repr__ = __str__ def _context(self): return self.cls context = property(_context, None, None, """Get context (class) of this test""") def setUp(self): try_run(self.inst, ('setup', 'setUp')) def tearDown(self): try_run(self.inst, ('teardown', 'tearDown')) def _descriptors(self): """in most cases, this is the method itself and no arguments. For tests generated by generator methods, the original (generator) method and args passed to the generated method or function are returned. """ if self.descriptor: return self.descriptor, self.arg else: return self.method, self.arg