Index: unittest.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/unittest.py,v retrieving revision 1.22 diff -c -r1.22 unittest.py *** unittest.py 27 Feb 2003 20:14:43 -0000 1.22 --- unittest.py 9 Apr 2003 22:28:11 -0000 *************** *** 54,59 **** --- 54,60 ---- import string import os import types + import sets ############################################################################## # Test framework core *************** *** 111,117 **** 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.""" --- 112,118 ---- 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.""" *************** *** 214,224 **** result.addError(self, self.__exc_info()) return ! ok = 0 try: testMethod() ! ok = 1 ! except self.failureException, e: result.addFailure(self, self.__exc_info()) except KeyboardInterrupt: raise --- 215,225 ---- result.addError(self, self.__exc_info()) return ! ok = False try: testMethod() ! ok = True ! except self.failureException, e: result.addFailure(self, self.__exc_info()) except KeyboardInterrupt: raise *************** *** 231,237 **** raise except: result.addError(self, self.__exc_info()) ! ok = 0 if ok: result.addSuccess(self) finally: result.stopTest(self) --- 232,238 ---- raise except: result.addError(self, self.__exc_info()) ! ok = False if ok: result.addSuccess(self) finally: result.stopTest(self) *************** *** 324,329 **** --- 325,342 ---- raise self.failureException, \ (msg or '%s == %s within %s places' % (`first`, `second`, `places`)) + def createMockInstance(self, classType, methods=[], *initArgs, + **initKwargs): + """Create a mock instance of specified type (classType) + See MockFactory.py for more detail + """ + self.__callStack = [] + mockObject = MockFactory.__new__(classType, methods, self.__callStack, *initArgs, **initKwargs) + return mockObject + + def getMockInstanceCalls(self): + return self.__callStack + assertEqual = assertEquals = failUnlessEqual assertNotEqual = assertNotEquals = failIfEqual *************** *** 693,699 **** in MyTestCase """ def __init__(self, module='__main__', defaultTest=None, ! argv=None, testRunner=None, testLoader=defaultTestLoader): if type(module) == type(''): self.module = __import__(module) for part in string.split(module,'.')[1:]: --- 706,713 ---- in MyTestCase """ def __init__(self, module='__main__', defaultTest=None, ! argv=None, testRunner=None, ! testLoader=defaultTestLoader, exitsOnResult=True): if type(module) == type(''): self.module = __import__(module) for part in string.split(module,'.')[1:]: *************** *** 703,714 **** if argv is None: argv = sys.argv self.verbosity = 1 self.defaultTest = defaultTest self.testRunner = testRunner self.testLoader = testLoader self.progName = os.path.basename(argv[0]) self.parseArgs(argv) ! self.runTests() def usageExit(self, msg=None): if msg: print msg --- 717,734 ---- if argv is None: argv = sys.argv self.verbosity = 1 + self.exitsOnResult = exitsOnResult self.defaultTest = defaultTest self.testRunner = testRunner self.testLoader = testLoader self.progName = os.path.basename(argv[0]) self.parseArgs(argv) ! self.result = self.runTests() ! ! def __repr__(self): ! return self.result ! ! getResult = __call__ = __repr__ def usageExit(self, msg=None): if msg: print msg *************** *** 746,754 **** if self.testRunner is None: self.testRunner = TextTestRunner(verbosity=self.verbosity) result = self.testRunner.run(self.test) ! sys.exit(not result.wasSuccessful()) main = TestProgram ############################################################################## --- 766,920 ---- if self.testRunner is None: self.testRunner = TextTestRunner(verbosity=self.verbosity) result = self.testRunner.run(self.test) ! if self.exitsOnResult: ! sys.exit(not result.wasSuccessful()) ! return result ! ! class MockError(TypeError): ! """\ ! Classes implementing __getattr__ and __getattribute__ cannot be mocked. ! Consider mocking the objects that those hooks operate on ! """ ! def __str__(self): ! return "%s\n\n%s" % (super(MockError, self).__str__(), self.__doc__) ! ! class EmptyMockSequence(IndexError): ! """Event Sequence of a mock method has been consumed""" ! ! ! class MockMethod(object): ! """ ! Provide introspection and manipulation of a method call. ! e.g override a method to raise an exception or return ! abituary values. ! """ ! ! def __init__(self, name, mockInstance, realMethod, callStack): ! """Construct the mock method with a method name, ! pass the orignal metod if you desure it to be called ! (still retains introspection features) ! and a callStack list to track what's been called overall ! """ ! object.__init__(self) ! self.__name__ = name ! self.instance = mockInstance ! self.realMethod = realMethod ! self._callStack = callStack ! self._kwargsPassed = [] ! self._argsPassed = [] ! ! def argsPassed(self): ! """argsPassed -> [argslistForFirstInvokation, argsListForSecondInvokation, ...]""" ! return self._argsPassed ! ! def kwargsPassed(self): ! return self._kwargsPassed ! ! def setException(self, exception): ! """Set an exception to raise for this method""" ! if not isinstance(exception, Exception): ! raise MockError("""\Cannot set exception ! that is not of base-type exceptions.Exception""") ! self.eventSequence = [exception] ! ! def setReturnValue(self, value): ! """Set a return value for this method""" ! self.eventSequence = [value] ! ! def setEventSequence(self, seq): ! """Set a sequence of events for this instance method ! Passing an exception in the sequence will cause this instance ! to raise that exception for you ! (thus aborting any subsequent calls that may be registered) ! """ ! self.eventSequence = seq[:] ! ! def __call__(self, *args, **kwargs): ! """Call this instance representing one of your instance's methods ! calls your instance's methods also if passed as a non-None value ! to this instance's constructor ! """ ! # Can we check the mock method has a similar interface to the real method? ! self._callStack.append(self.__name__) ! self._argsPassed.append(args) ! self._kwargsPassed.append(kwargs) ! obj = None ! ! if self.realMethod is not None: ! obj = self.realMethod(*args, **kwargs) ! ! if hasattr(self, "eventSequence"): ! try: ! obj = self.eventSequence.pop(0) ! except IndexError, ie: ! raise EmptyMockSequence("""\ ! You have called mock method (%s) %s times, ! but that many events have not been set ! (set events via setEventSequence/setExcpetion/setReturnValue) ! """ %(self.__name__, len(self._argsPassed))) ! else: ! if isinstance(obj, Exception): ! raise obj ! ! return obj ! ! class MockFactory(object): ! """MockObject Support For TestCase""" ! ! def __new__(classDef, mockMethods, callStack, *args, **kwargs): ! """__new__(classDef, mockMethods, callStack, *initArgsm, **initKwArgs ! ! classDef - The Class you want to test ! mockMethods - Pass a list of methods that you want to override # ! Any method passed in this list will return None by default, ! leaving you as the tester to override that method to return some arbutary ! value or raise an exception. ! ! Passing an empty list will cause all methods in the object to call ! the original methods on your classDef, but addtioanlly can still ! introspect (agsPassed etc) ! ! callStack - list to hold call information, usually an empty list object ! *initArgs & ! **initKwargs - Arguments to passed to the constructor of your classDef ! """ ! self = classDef(*args, **kwargs) ! all = sets.Set(dir(self)) ! ! if '__getattr__' in all: ! raise MockError() ! ! forMocking = sets.Set(mockMethods) ! callables = sets.Set([ name for name in all \ ! if callable(getattr(self, name)) \ ! and not name.startswith('__') ]) ! ! nonCallables = all.difference(callables) ! mockWithReal = callables.difference(forMocking) ! ! if not forMocking.issubset(callables): ! raise AttributeError(""" ! Some specified method(s)(%s)do not exist on %s ! or is not a callable instance method ! """ % (''.join(forMocking.difference(callables)), classDef)) ! ! # now we are sure not to have any undefined method(s) ! totalOverrides = forMocking.intersection(callables) ! ! for name in all: ! attr = realMethod = getattr(self, name) ! if name in nonCallables: ! continue ! if name in totalOverrides: ! realMethod = None ! mockMethod = MockMethod(name, self, realMethod, callStack) ! setattr(self, name, mockMethod) ! ! return self ! main = TestProgram + ##############################################################################