![](https://secure.gravatar.com/avatar/7cb1aa083f8c752da1b3e236bcf284d7.jpg?s=120&d=mm&r=g)
Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1:/tmp/cvs-serv29369 Modified Files: unittest.py Log Message: - Fixed loading of tests by name when name refers to unbound method (PyUnit issue 563882, thanks to Alexandre Fayolle) - Ignore non-callable attributes of classes when searching for test method names (PyUnit issue 769338, thanks to Seth Falcon) - New assertTrue and assertFalse aliases for comfort of JUnit users - Automatically discover 'runTest()' test methods (PyUnit issue 469444, thanks to Roeland Rengelink) - Dropped Python 1.5.2 compatibility, merged appropriate shortcuts from Python CVS; should work with Python >= 2.1. - Removed all references to string module by using string methods instead Index: unittest.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/unittest.py,v retrieving revision 1.26 retrieving revision 1.27 diff -C2 -d -r1.26 -r1.27 *** unittest.py 15 Sep 2003 11:01:21 -0000 1.26 --- unittest.py 22 Sep 2003 11:08:12 -0000 1.27 *************** *** 28,32 **** http://pyunit.sourceforge.net/ ! Copyright (c) 1999, 2000, 2001 Steve Purcell This module is free software, and you may redistribute it and/or modify it under the same terms as Python itself, so long as this copyright message --- 28,32 ---- http://pyunit.sourceforge.net/ ! Copyright (c) 1999-2003 Steve Purcell This module is free software, and you may redistribute it and/or modify it under the same terms as Python itself, so long as this copyright message *************** *** 47,56 **** __author__ = "Steve Purcell" __email__ = "stephen_purcell at yahoo dot com" ! __version__ = "#Revision: 1.46 $"[11:-2] import time import sys import traceback - import string import os import types --- 47,55 ---- __author__ = "Steve Purcell" __email__ = "stephen_purcell at yahoo dot com" ! __version__ = "#Revision: 1.56 $"[11:-2] import time import sys import traceback import os import types *************** *** 62,70 **** 'TestLoader', 'FunctionTestCase', 'main', 'defaultTestLoader'] ! # Expose obsolete functions for backwards compatability __all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases']) ############################################################################## # Test framework core ############################################################################## --- 61,85 ---- 'TestLoader', 'FunctionTestCase', 'main', 'defaultTestLoader'] ! # Expose obsolete functions for backwards compatibility __all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases']) ############################################################################## + # Backward compatibility + ############################################################################## + if sys.version_info[:2] < (2, 2): + False, True = 0, 1 + def isinstance(obj, clsinfo): + import __builtin__ + if type(clsinfo) in (types.TupleType, types.ListType): + for cls in clsinfo: + if cls is type: cls = types.ClassType + if __builtin__.isinstance(obj, cls): + return 1 + return 0 + else: return __builtin__.isinstance(obj, clsinfo) + + + ############################################################################## # Test framework core ############################################################################## *************** *** 122,130 **** def stop(self): "Indicates that the tests should be aborted" ! self.shouldStop = 1 def _exc_info_to_string(self, err): """Converts a sys.exc_info()-style tuple of values into a string.""" ! return string.join(traceback.format_exception(*err), '') def __repr__(self): --- 137,145 ---- def stop(self): "Indicates that the tests should be aborted" ! self.shouldStop = True def _exc_info_to_string(self, err): """Converts a sys.exc_info()-style tuple of values into a string.""" ! return ''.join(traceback.format_exception(*err)) def __repr__(self): *************** *** 197,201 **** """ doc = self.__testMethodDoc ! return doc and string.strip(string.split(doc, "\n")[0]) or None def id(self): --- 212,216 ---- """ doc = self.__testMethodDoc ! return doc and doc.split("\n")[0].strip() or None def id(self): *************** *** 210,216 **** def run(self, result=None): - return self(result) - - def __call__(self, result=None): if result is None: result = self.defaultTestResult() result.startTest(self) --- 225,228 ---- *************** *** 225,232 **** return ! ok = 0 try: testMethod() ! ok = 1 except self.failureException: result.addFailure(self, self.__exc_info()) --- 237,244 ---- return ! ok = False try: testMethod() ! ok = True except self.failureException: result.addFailure(self, self.__exc_info()) *************** *** 242,250 **** except: result.addError(self, self.__exc_info()) ! ok = 0 if ok: result.addSuccess(self) finally: result.stopTest(self) def debug(self): """Run the test without collecting errors in a TestResult""" --- 254,264 ---- except: result.addError(self, self.__exc_info()) ! ok = False if ok: result.addSuccess(self) finally: result.stopTest(self) + __call__ = run + def debug(self): """Run the test without collecting errors in a TestResult""" *************** *** 293,297 **** if hasattr(excClass,'__name__'): excName = excClass.__name__ else: excName = str(excClass) ! raise self.failureException, excName def failUnlessEqual(self, first, second, msg=None): --- 307,311 ---- if hasattr(excClass,'__name__'): excName = excClass.__name__ else: excName = str(excClass) ! raise self.failureException, "%s not raised" % excName def failUnlessEqual(self, first, second, msg=None): *************** *** 335,338 **** --- 349,354 ---- (msg or '%s == %s within %s places' % (`first`, `second`, `places`)) + # Synonyms for assertion methods + assertEqual = assertEquals = failUnlessEqual *************** *** 345,349 **** assertRaises = failUnlessRaises ! assert_ = failUnless --- 361,367 ---- assertRaises = failUnlessRaises ! assert_ = assertTrue = failUnless ! ! assertFalse = failIf *************** *** 370,374 **** cases = 0 for test in self._tests: ! cases = cases + test.countTestCases() return cases --- 388,392 ---- cases = 0 for test in self._tests: ! cases += test.countTestCases() return cases *************** *** 435,439 **** if self.__description is not None: return self.__description doc = self.__testFunc.__doc__ ! return doc and string.strip(string.split(doc, "\n")[0]) or None --- 453,457 ---- if self.__description is not None: return self.__description doc = self.__testFunc.__doc__ ! return doc and doc.split("\n")[0].strip() or None *************** *** 453,458 **** def loadTestsFromTestCase(self, testCaseClass): """Return a suite of all tests cases contained in testCaseClass""" ! return self.suiteClass(map(testCaseClass, ! self.getTestCaseNames(testCaseClass))) def loadTestsFromModule(self, module): --- 471,478 ---- def loadTestsFromTestCase(self, testCaseClass): """Return a suite of all tests cases contained in testCaseClass""" ! testCaseNames = self.getTestCaseNames(testCaseClass) ! if not testCaseNames and hasattr(testCaseClass, 'runTest'): ! testCaseNames = ['runTest'] ! return self.suiteClass(map(testCaseClass, testCaseNames)) def loadTestsFromModule(self, module): *************** *** 475,495 **** The method optionally resolves the names relative to a given module. """ ! parts = string.split(name, '.') if module is None: ! if not parts: ! raise ValueError, "incomplete test name: %s" % name ! else: ! parts_copy = parts[:] ! while parts_copy: ! try: ! module = __import__(string.join(parts_copy,'.')) ! break ! except ImportError: ! del parts_copy[-1] ! if not parts_copy: raise parts = parts[1:] obj = module for part in parts: ! obj = getattr(obj, part) import unittest --- 495,512 ---- The method optionally resolves the names relative to a given module. """ ! parts = name.split('.') if module is None: ! parts_copy = parts[:] ! while parts_copy: ! try: ! module = __import__('.'.join(parts_copy)) ! break ! except ImportError: ! del parts_copy[-1] ! if not parts_copy: raise parts = parts[1:] obj = module for part in parts: ! parent, obj = obj, getattr(obj, part) import unittest *************** *** 500,508 **** return self.loadTestsFromTestCase(obj) elif type(obj) == types.UnboundMethodType: return obj.im_class(obj.__name__) elif callable(obj): test = obj() ! if not isinstance(test, unittest.TestCase) and \ ! not isinstance(test, unittest.TestSuite): raise ValueError, \ "calling %s returned %s, not a test" % (obj,test) --- 517,527 ---- return self.loadTestsFromTestCase(obj) elif type(obj) == types.UnboundMethodType: + return parent(obj.__name__) return obj.im_class(obj.__name__) + elif isinstance(obj, unittest.TestSuite): + return obj elif callable(obj): test = obj() ! if not isinstance(test, (unittest.TestCase, unittest.TestSuite)): raise ValueError, \ "calling %s returned %s, not a test" % (obj,test) *************** *** 515,521 **** of string specifiers. See 'loadTestsFromName()'. """ ! suites = [] ! for name in names: ! suites.append(self.loadTestsFromName(name, module)) return self.suiteClass(suites) --- 534,538 ---- of string specifiers. See 'loadTestsFromName()'. """ ! suites = [self.loadTestsFromName(name, module) for name in names] return self.suiteClass(suites) *************** *** 523,528 **** """Return a sorted sequence of method names found within testCaseClass """ ! testFnNames = filter(lambda n,p=self.testMethodPrefix: n[:len(p)] == p, ! dir(testCaseClass)) for baseclass in testCaseClass.__bases__: for testFnName in self.getTestCaseNames(baseclass): --- 540,546 ---- """Return a sorted sequence of method names found within testCaseClass """ ! def isTestMethod(attrname, testCaseClass=testCaseClass, prefix=self.testMethodPrefix): ! return attrname[:len(prefix)] == prefix and callable(getattr(testCaseClass, attrname)) ! testFnNames = filter(isTestMethod, dir(testCaseClass)) for baseclass in testCaseClass.__bases__: for testFnName in self.getTestCaseNames(baseclass): *************** *** 707,711 **** if type(module) == type(''): self.module = __import__(module) ! for part in string.split(module,'.')[1:]: self.module = getattr(self.module, part) else: --- 725,729 ---- if type(module) == type(''): self.module = __import__(module) ! for part in module.split('.')[1:]: self.module = getattr(self.module, part) else: