Code

removed a print
[roundup.git] / test / unittest.py
1 #!/usr/bin/env python
2 '''
3 Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
4 Smalltalk testing framework.
6 This module contains the core framework classes that form the basis of
7 specific test cases and suites (TestCase, TestSuite etc.), and also a
8 text-based utility class for running the tests and reporting the results
9 (TextTestRunner).
11 Simple usage:
13     import unittest
15     class IntegerArithmenticTestCase(unittest.TestCase):
16         def testAdd(self):  ## test method names begin 'test*'
17             self.assertEquals((1 + 2), 3)
18             self.assertEquals(0 + 1, 1)
19         def testMultiply(self);
20             self.assertEquals((0 * 10), 0)
21             self.assertEquals((5 * 8), 40)
23     if __name__ == '__main__':
24         unittest.main()
26 Further information is available in the bundled documentation, and from
28   http://pyunit.sourceforge.net/
30 Copyright (c) 1999, 2000, 2001 Steve Purcell
31 This module is free software, and you may redistribute it and/or modify
32 it under the same terms as Python itself, so long as this copyright message
33 and disclaimer are retained in their original form.
35 IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
36 SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
37 THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
38 DAMAGE.
40 THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
41 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
42 PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
43 AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
44 SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
45 '''
47 __author__ = "Steve Purcell"
48 __email__ = "stephen_purcell at yahoo dot com"
49 __version__ = "$Revision: 1.2 $"[11:-2]
51 import time
52 import sys
53 import traceback
54 import string
55 import os
56 import types
58 ##############################################################################
59 # Test framework core
60 ##############################################################################
62 class TestResult:
63     """Holder for test result information.
65     Test results are automatically managed by the TestCase and TestSuite
66     classes, and do not need to be explicitly manipulated by writers of tests.
68     Each instance holds the total number of tests run, and collections of
69     failures and errors that occurred among those test runs. The collections
70     contain tuples of (testcase, exceptioninfo), where exceptioninfo is a
71     tuple of values as returned by sys.exc_info().
72     """
73     def __init__(self):
74         self.failures = []
75         self.errors = []
76         self.testsRun = 0
77         self.shouldStop = 0
79     def startTest(self, test):
80         "Called when the given test is about to be run"
81         self.testsRun = self.testsRun + 1
83     def stopTest(self, test):
84         "Called when the given test has been run"
85         pass
87     def addError(self, test, err):
88         "Called when an error has occurred"
89         self.errors.append((test, err))
91     def addFailure(self, test, err):
92         "Called when a failure has occurred"
93         self.failures.append((test, err))
95     def addSuccess(self, test):
96         "Called when a test has completed successfully"
97         pass
99     def wasSuccessful(self):
100         "Tells whether or not this result was a success"
101         return len(self.failures) == len(self.errors) == 0
103     def stop(self):
104         "Indicates that the tests should be aborted"
105         self.shouldStop = 1
107     def __repr__(self):
108         return "<%s run=%i errors=%i failures=%i>" % \
109                (self.__class__, self.testsRun, len(self.errors),
110                 len(self.failures))
113 class TestCase:
114     """A class whose instances are single test cases.
116     By default, the test code itself should be placed in a method named
117     'runTest'.
119     If the fixture may be used for many test cases, create as
120     many test methods as are needed. When instantiating such a TestCase
121     subclass, specify in the constructor arguments the name of the test method
122     that the instance is to execute.
124     Test authors should subclass TestCase for their own tests. Construction
125     and deconstruction of the test's environment ('fixture') can be
126     implemented by overriding the 'setUp' and 'tearDown' methods respectively.
128     If it is necessary to override the __init__ method, the base class
129     __init__ method must always be called. It is important that subclasses
130     should not change the signature of their __init__ method, since instances
131     of the classes are instantiated automatically by parts of the framework
132     in order to be run.
133     """
135     # This attribute determines which exception will be raised when
136     # the instance's assertion methods fail; test methods raising this
137     # exception will be deemed to have 'failed' rather than 'errored'
139     failureException = AssertionError
141     def __init__(self, methodName='runTest'):
142         """Create an instance of the class that will use the named test
143            method when executed. Raises a ValueError if the instance does
144            not have a method with the specified name.
145         """
146         try:
147             self.__testMethodName = methodName
148             testMethod = getattr(self, methodName)
149             self.__testMethodDoc = testMethod.__doc__
150         except AttributeError:
151             raise ValueError, "no such test method in %s: %s" % \
152                   (self.__class__, methodName)
154     def setUp(self):
155         "Hook method for setting up the test fixture before exercising it."
156         pass
158     def tearDown(self):
159         "Hook method for deconstructing the test fixture after testing it."
160         pass
162     def countTestCases(self):
163         return 1
165     def defaultTestResult(self):
166         return TestResult()
168     def shortDescription(self):
169         """Returns a one-line description of the test, or None if no
170         description has been provided.
172         The default implementation of this method returns the first line of
173         the specified test method's docstring.
174         """
175         doc = self.__testMethodDoc
176         return doc and string.strip(string.split(doc, "\n")[0]) or None
178     def id(self):
179         return "%s.%s" % (self.__class__, self.__testMethodName)
181     def __str__(self):
182         return "%s (%s)" % (self.__testMethodName, self.__class__)
184     def __repr__(self):
185         return "<%s testMethod=%s>" % \
186                (self.__class__, self.__testMethodName)
188     def run(self, result=None):
189         return self(result)
191     def __call__(self, result=None):
192         if result is None: result = self.defaultTestResult()
193         result.startTest(self)
194         testMethod = getattr(self, self.__testMethodName)
195         try:
196             try:
197                 self.setUp()
198             except:
199                 result.addError(self,self.__exc_info())
200                 return
202             ok = 0
203             try:
204                 testMethod()
205                 ok = 1
206             except self.failureException, e:
207                 result.addFailure(self,self.__exc_info())
208             except:
209                 result.addError(self,self.__exc_info())
211             try:
212                 self.tearDown()
213             except:
214                 result.addError(self,self.__exc_info())
215                 ok = 0
216             if ok: result.addSuccess(self)
217         finally:
218             result.stopTest(self)
220     def debug(self):
221         """Run the test without collecting errors in a TestResult"""
222         self.setUp()
223         getattr(self, self.__testMethodName)()
224         self.tearDown()
226     def __exc_info(self):
227         """Return a version of sys.exc_info() with the traceback frame
228            minimised; usually the top level of the traceback frame is not
229            needed.
230         """
231         exctype, excvalue, tb = sys.exc_info()
232         if sys.platform[:4] == 'java': ## tracebacks look different in Jython
233             return (exctype, excvalue, tb)
234         newtb = tb.tb_next
235         if newtb is None:
236             return (exctype, excvalue, tb)
237         return (exctype, excvalue, newtb)
239     def fail(self, msg=None):
240         """Fail immediately, with the given message."""
241         raise self.failureException, msg
243     def failIf(self, expr, msg=None):
244         "Fail the test if the expression is true."
245         if expr: raise self.failureException, msg
247     def failUnless(self, expr, msg=None):
248         """Fail the test unless the expression is true."""
249         if not expr: raise self.failureException, msg
251     def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
252         """Fail unless an exception of class excClass is thrown
253            by callableObj when invoked with arguments args and keyword
254            arguments kwargs. If a different type of exception is
255            thrown, it will not be caught, and the test case will be
256            deemed to have suffered an error, exactly as for an
257            unexpected exception.
258         """
259         try:
260             apply(callableObj, args, kwargs)
261         except excClass:
262             return
263         else:
264             if hasattr(excClass,'__name__'): excName = excClass.__name__
265             else: excName = str(excClass)
266             raise self.failureException, excName
268     def failUnlessEqual(self, first, second, msg=None):
269         """Fail if the two objects are unequal as determined by the '!='
270            operator.
271         """
272         if first != second:
273             raise self.failureException, (msg or '%s != %s' % (first, second))
275     def failIfEqual(self, first, second, msg=None):
276         """Fail if the two objects are equal as determined by the '=='
277            operator.
278         """
279         if first == second:
280             raise self.failureException, (msg or '%s == %s' % (first, second))
282     assertEqual = assertEquals = failUnlessEqual
284     assertNotEqual = assertNotEquals = failIfEqual
286     assertRaises = failUnlessRaises
288     assert_ = failUnless
292 class TestSuite:
293     """A test suite is a composite test consisting of a number of TestCases.
295     For use, create an instance of TestSuite, then add test case instances.
296     When all tests have been added, the suite can be passed to a test
297     runner, such as TextTestRunner. It will run the individual test cases
298     in the order in which they were added, aggregating the results. When
299     subclassing, do not forget to call the base class constructor.
300     """
301     def __init__(self, tests=()):
302         self._tests = []
303         self.addTests(tests)
305     def __repr__(self):
306         return "<%s tests=%s>" % (self.__class__, self._tests)
308     __str__ = __repr__
310     def countTestCases(self):
311         cases = 0
312         for test in self._tests:
313             cases = cases + test.countTestCases()
314         return cases
316     def addTest(self, test):
317         self._tests.append(test)
319     def addTests(self, tests):
320         for test in tests:
321             self.addTest(test)
323     def run(self, result):
324         return self(result)
326     def __call__(self, result):
327         for test in self._tests:
328             if result.shouldStop:
329                 break
330             test(result)
331         return result
333     def debug(self):
334         """Run the tests without collecting errors in a TestResult"""
335         for test in self._tests: test.debug()
338 class FunctionTestCase(TestCase):
339     """A test case that wraps a test function.
341     This is useful for slipping pre-existing test functions into the
342     PyUnit framework. Optionally, set-up and tidy-up functions can be
343     supplied. As with TestCase, the tidy-up ('tearDown') function will
344     always be called if the set-up ('setUp') function ran successfully.
345     """
347     def __init__(self, testFunc, setUp=None, tearDown=None,
348                  description=None):
349         TestCase.__init__(self)
350         self.__setUpFunc = setUp
351         self.__tearDownFunc = tearDown
352         self.__testFunc = testFunc
353         self.__description = description
355     def setUp(self):
356         if self.__setUpFunc is not None:
357             self.__setUpFunc()
359     def tearDown(self):
360         if self.__tearDownFunc is not None:
361             self.__tearDownFunc()
363     def runTest(self):
364         self.__testFunc()
366     def id(self):
367         return self.__testFunc.__name__
369     def __str__(self):
370         return "%s (%s)" % (self.__class__, self.__testFunc.__name__)
372     def __repr__(self):
373         return "<%s testFunc=%s>" % (self.__class__, self.__testFunc)
375     def shortDescription(self):
376         if self.__description is not None: return self.__description
377         doc = self.__testFunc.__doc__
378         return doc and string.strip(string.split(doc, "\n")[0]) or None
382 ##############################################################################
383 # Locating and loading tests
384 ##############################################################################
386 class TestLoader:
387     """This class is responsible for loading tests according to various
388     criteria and returning them wrapped in a Test
389     """
390     testMethodPrefix = 'test'
391     sortTestMethodsUsing = cmp
392     suiteClass = TestSuite
394     def loadTestsFromTestCase(self, testCaseClass):
395         """Return a suite of all tests cases contained in testCaseClass"""
396         return self.suiteClass(map(testCaseClass,
397                                    self.getTestCaseNames(testCaseClass)))
399     def loadTestsFromModule(self, module):
400         """Return a suite of all tests cases contained in the given module"""
401         tests = []
402         for name in dir(module):
403             obj = getattr(module, name)
404             if type(obj) == types.ClassType and issubclass(obj, TestCase):
405                 tests.append(self.loadTestsFromTestCase(obj))
406         return self.suiteClass(tests)
408     def loadTestsFromName(self, name, module=None):
409         """Return a suite of all tests cases given a string specifier.
411         The name may resolve either to a module, a test case class, a
412         test method within a test case class, or a callable object which
413         returns a TestCase or TestSuite instance.
415         The method optionally resolves the names relative to a given module.
416         """
417         parts = string.split(name, '.')
418         if module is None:
419             if not parts:
420                 raise ValueError, "incomplete test name: %s" % name
421             else:
422                 parts_copy = parts[:]
423                 while parts_copy:
424                     try:
425                         module = __import__(string.join(parts_copy,'.'))
426                         break
427                     except ImportError:
428                         del parts_copy[-1]
429                         if not parts_copy: raise
430                 parts = parts[1:]
431         obj = module
432         for part in parts:
433             obj = getattr(obj, part)
435         if type(obj) == types.ModuleType:
436             return self.loadTestsFromModule(obj)
437         elif type(obj) == types.ClassType and issubclass(obj, TestCase):
438             return self.loadTestsFromTestCase(obj)
439         elif type(obj) == types.UnboundMethodType:
440             return obj.im_class(obj.__name__)
441         elif callable(obj):
442             test = obj()
443             if not isinstance(test, TestCase) and \
444                not isinstance(test, TestSuite):
445                 raise ValueError, \
446                       "calling %s returned %s, not a test" % (obj,test)
447             return test
448         else:
449             raise ValueError, "don't know how to make test from: %s" % obj
451     def loadTestsFromNames(self, names, module=None):
452         """Return a suite of all tests cases found using the given sequence
453         of string specifiers. See 'loadTestsFromName()'.
454         """
455         suites = []
456         for name in names:
457             suites.append(self.loadTestsFromName(name, module))
458         return self.suiteClass(suites)
460     def getTestCaseNames(self, testCaseClass):
461         """Return a sorted sequence of method names found within testCaseClass
462         """
463         testFnNames = filter(lambda n,p=self.testMethodPrefix: n[:len(p)] == p,
464                              dir(testCaseClass))
465         for baseclass in testCaseClass.__bases__:
466             for testFnName in self.getTestCaseNames(baseclass):
467                 if testFnName not in testFnNames:  # handle overridden methods
468                     testFnNames.append(testFnName)
469         if self.sortTestMethodsUsing:
470             testFnNames.sort(self.sortTestMethodsUsing)
471         return testFnNames
475 defaultTestLoader = TestLoader()
478 ##############################################################################
479 # Patches for old functions: these functions should be considered obsolete
480 ##############################################################################
482 def _makeLoader(prefix, sortUsing, suiteClass=None):
483     loader = TestLoader()
484     loader.sortTestMethodsUsing = sortUsing
485     loader.testMethodPrefix = prefix
486     if suiteClass: loader.suiteClass = suiteClass
487     return loader
489 def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
490     return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
492 def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
493     return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
495 def findTestCases(module, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
496     return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
499 ##############################################################################
500 # Text UI
501 ##############################################################################
503 class _WritelnDecorator:
504     """Used to decorate file-like objects with a handy 'writeln' method"""
505     def __init__(self,stream):
506         self.stream = stream
508     def __getattr__(self, attr):
509         return getattr(self.stream,attr)
511     def writeln(self, *args):
512         if args: apply(self.write, args)
513         self.write('\n') # text-mode streams translate to \r\n if needed
516 class _TextTestResult(TestResult):
517     """A test result class that can print formatted text results to a stream.
519     Used by TextTestRunner.
520     """
521     separator1 = '=' * 70
522     separator2 = '-' * 70
524     def __init__(self, stream, descriptions, verbosity):
525         TestResult.__init__(self)
526         self.stream = stream
527         self.showAll = verbosity > 1
528         self.dots = verbosity == 1
529         self.descriptions = descriptions
531     def getDescription(self, test):
532         if self.descriptions:
533             return test.shortDescription() or str(test)
534         else:
535             return str(test)
537     def startTest(self, test):
538         TestResult.startTest(self, test)
539         if self.showAll:
540             self.stream.write(self.getDescription(test))
541             self.stream.write(" ... ")
543     def addSuccess(self, test):
544         TestResult.addSuccess(self, test)
545         if self.showAll:
546             self.stream.writeln("ok")
547         elif self.dots:
548             self.stream.write('.')
550     def addError(self, test, err):
551         TestResult.addError(self, test, err)
552         if self.showAll:
553             self.stream.writeln("ERROR")
554         elif self.dots:
555             self.stream.write('E')
556         if err[0] is KeyboardInterrupt:
557             self.shouldStop = 1
559     def addFailure(self, test, err):
560         TestResult.addFailure(self, test, err)
561         if self.showAll:
562             self.stream.writeln("FAIL")
563         elif self.dots:
564             self.stream.write('F')
566     def printErrors(self):
567         if self.dots or self.showAll:
568             self.stream.writeln()
569         self.printErrorList('ERROR', self.errors)
570         self.printErrorList('FAIL', self.failures)
572     def printErrorList(self, flavour, errors):
573         for test, err in errors:
574             self.stream.writeln(self.separator1)
575             self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
576             self.stream.writeln(self.separator2)
577             for line in apply(traceback.format_exception, err):
578                 for l in string.split(line,"\n")[:-1]:
579                     self.stream.writeln("%s" % l)
582 class TextTestRunner:
583     """A test runner class that displays results in textual form.
585     It prints out the names of tests as they are run, errors as they
586     occur, and a summary of the results at the end of the test run.
587     """
588     def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1):
589         self.stream = _WritelnDecorator(stream)
590         self.descriptions = descriptions
591         self.verbosity = verbosity
593     def _makeResult(self):
594         return _TextTestResult(self.stream, self.descriptions, self.verbosity)
596     def run(self, test):
597         "Run the given test case or test suite."
598         result = self._makeResult()
599         startTime = time.time()
600         test(result)
601         stopTime = time.time()
602         timeTaken = float(stopTime - startTime)
603         result.printErrors()
604         self.stream.writeln(result.separator2)
605         run = result.testsRun
606         self.stream.writeln("Ran %d test%s in %.3fs" %
607                             (run, run == 1 and "" or "s", timeTaken))
608         self.stream.writeln()
609         if not result.wasSuccessful():
610             self.stream.write("FAILED (")
611             failed, errored = map(len, (result.failures, result.errors))
612             if failed:
613                 self.stream.write("failures=%d" % failed)
614             if errored:
615                 if failed: self.stream.write(", ")
616                 self.stream.write("errors=%d" % errored)
617             self.stream.writeln(")")
618         else:
619             self.stream.writeln("OK")
620         return result
624 ##############################################################################
625 # Facilities for running tests from the command line
626 ##############################################################################
628 class TestProgram:
629     """A command-line program that runs a set of tests; this is primarily
630        for making test modules conveniently executable.
631     """
632     USAGE = """\
633 Usage: %(progName)s [options] [test] [...]
635 Options:
636   -h, --help       Show this message
637   -v, --verbose    Verbose output
638   -q, --quiet      Minimal output
640 Examples:
641   %(progName)s                               - run default set of tests
642   %(progName)s MyTestSuite                   - run suite 'MyTestSuite'
643   %(progName)s MyTestCase.testSomething      - run MyTestCase.testSomething
644   %(progName)s MyTestCase                    - run all 'test*' test methods
645                                                in MyTestCase
646 """
647     def __init__(self, module='__main__', defaultTest=None,
648                  argv=None, testRunner=None, testLoader=defaultTestLoader):
649         if type(module) == type(''):
650             self.module = __import__(module)
651             for part in string.split(module,'.')[1:]:
652                 self.module = getattr(self.module, part)
653         else:
654             self.module = module
655         if argv is None:
656             argv = sys.argv
657         self.verbosity = 1
658         self.defaultTest = defaultTest
659         self.testRunner = testRunner
660         self.testLoader = testLoader
661         self.progName = os.path.basename(argv[0])
662         self.parseArgs(argv)
663         self.runTests()
665     def usageExit(self, msg=None):
666         if msg: print msg
667         print self.USAGE % self.__dict__
668         sys.exit(2)
670     def parseArgs(self, argv):
671         import getopt
672         try:
673             options, args = getopt.getopt(argv[1:], 'hHvq',
674                                           ['help','verbose','quiet'])
675             for opt, value in options:
676                 if opt in ('-h','-H','--help'):
677                     self.usageExit()
678                 if opt in ('-q','--quiet'):
679                     self.verbosity = 0
680                 if opt in ('-v','--verbose'):
681                     self.verbosity = 2
682             if len(args) == 0 and self.defaultTest is None:
683                 self.test = self.testLoader.loadTestsFromModule(self.module)
684                 return
685             if len(args) > 0:
686                 self.testNames = args
687             else:
688                 self.testNames = (self.defaultTest,)
689             self.createTests()
690         except getopt.error, msg:
691             self.usageExit(msg)
693     def createTests(self):
694         self.test = self.testLoader.loadTestsFromNames(self.testNames,
695                                                        self.module)
697     def runTests(self):
698         if self.testRunner is None:
699             self.testRunner = TextTestRunner(verbosity=self.verbosity)
700         result = self.testRunner.run(self.test)
701         sys.exit(not result.wasSuccessful())
703 main = TestProgram
706 ##############################################################################
707 # Executing this module from the command line
708 ##############################################################################
710 if __name__ == "__main__":
711     main(module=None)