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
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__':
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
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.
47 __author__
= "Steve Purcell"
48 __email__
= "stephen_purcell at yahoo dot com"
49 __version__
= "#Revision: 1.46 $"[11:-2]
58 ##############################################################################
59 # Exported classes and functions
60 ##############################################################################
61 __all__
= ['TestResult', 'TestCase', 'TestSuite', 'TextTestRunner',
62 'TestLoader', 'FunctionTestCase', 'main', 'defaultTestLoader']
64 # Expose obsolete functions for backwards compatability
65 __all__
.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
68 ##############################################################################
70 ##############################################################################
72 # All classes defined herein are 'new-style' classes, allowing use of 'super()'
76 return "%s.%s" % (cls
.__module
__, cls
.__name
__)
79 """Holder for test result information.
81 Test results are automatically managed by the TestCase and TestSuite
82 classes, and do not need to be explicitly manipulated by writers of tests.
84 Each instance holds the total number of tests run, and collections of
85 failures and errors that occurred among those test runs. The collections
86 contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
87 formatted traceback of the error that occurred.
95 def startTest(self
, test
):
96 "Called when the given test is about to be run"
97 self
.testsRun
= self
.testsRun
+ 1
99 def stopTest(self
, test
):
100 "Called when the given test has been run"
103 def addError(self
, test
, err
):
104 """Called when an error has occurred. 'err' is a tuple of values as
105 returned by sys.exc_info().
107 self
.errors
.append((test
, self
._exc
_info
_to
_string
(err
)))
109 def addFailure(self
, test
, err
):
110 """Called when an error has occurred. 'err' is a tuple of values as
111 returned by sys.exc_info()."""
112 self
.failures
.append((test
, self
._exc
_info
_to
_string
(err
)))
114 def addSuccess(self
, test
):
115 "Called when a test has completed successfully"
118 def wasSuccessful(self
):
119 "Tells whether or not this result was a success"
120 return len(self
.failures
) == len(self
.errors
) == 0
123 "Indicates that the tests should be aborted"
126 def _exc_info_to_string(self
, err
):
127 """Converts a sys.exc_info()-style tuple of values into a string."""
128 return string
.join(traceback
.format_exception(*err
), '')
131 return "<%s run=%i errors=%i failures=%i>" % \
132 (_strclass(self
.__class
__), self
.testsRun
, len(self
.errors
),
137 """A class whose instances are single test cases.
139 By default, the test code itself should be placed in a method named
142 If the fixture may be used for many test cases, create as
143 many test methods as are needed. When instantiating such a TestCase
144 subclass, specify in the constructor arguments the name of the test method
145 that the instance is to execute.
147 Test authors should subclass TestCase for their own tests. Construction
148 and deconstruction of the test's environment ('fixture') can be
149 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
151 If it is necessary to override the __init__ method, the base class
152 __init__ method must always be called. It is important that subclasses
153 should not change the signature of their __init__ method, since instances
154 of the classes are instantiated automatically by parts of the framework
158 # This attribute determines which exception will be raised when
159 # the instance's assertion methods fail; test methods raising this
160 # exception will be deemed to have 'failed' rather than 'errored'
162 failureException
= AssertionError
164 def __init__(self
, methodName
='runTest'):
165 """Create an instance of the class that will use the named test
166 method when executed. Raises a ValueError if the instance does
167 not have a method with the specified name.
170 self
.__testMethodName
= methodName
171 testMethod
= getattr(self
, methodName
)
172 self
.__testMethodDoc
= testMethod
.__doc
__
173 except AttributeError:
174 raise ValueError, "no such test method in %s: %s" % \
175 (self
.__class
__, methodName
)
178 "Hook method for setting up the test fixture before exercising it."
182 "Hook method for deconstructing the test fixture after testing it."
185 def countTestCases(self
):
188 def defaultTestResult(self
):
191 def shortDescription(self
):
192 """Returns a one-line description of the test, or None if no
193 description has been provided.
195 The default implementation of this method returns the first line of
196 the specified test method's docstring.
198 doc
= self
.__testMethodDoc
199 return doc
and string
.strip(string
.split(doc
, "\n")[0]) or None
202 return "%s.%s" % (_strclass(self
.__class
__), self
.__testMethodName
)
205 return "%s (%s)" % (self
.__testMethodName
, _strclass(self
.__class
__))
208 return "<%s testMethod=%s>" % \
209 (_strclass(self
.__class
__), self
.__testMethodName
)
211 def run(self
, result
=None):
214 def __call__(self
, result
=None):
215 if result
is None: result
= self
.defaultTestResult()
216 result
.startTest(self
)
217 testMethod
= getattr(self
, self
.__testMethodName
)
221 except KeyboardInterrupt:
224 result
.addError(self
, self
.__exc
_info
())
231 except self
.failureException
:
232 result
.addFailure(self
, self
.__exc
_info
())
233 except KeyboardInterrupt:
236 result
.addError(self
, self
.__exc
_info
())
240 except KeyboardInterrupt:
243 result
.addError(self
, self
.__exc
_info
())
245 if ok
: result
.addSuccess(self
)
247 result
.stopTest(self
)
250 """Run the test without collecting errors in a TestResult"""
252 getattr(self
, self
.__testMethodName
)()
255 def __exc_info(self
):
256 """Return a version of sys.exc_info() with the traceback frame
257 minimised; usually the top level of the traceback frame is not
260 exctype
, excvalue
, tb
= sys
.exc_info()
261 if sys
.platform
[:4] == 'java': ## tracebacks look different in Jython
262 return (exctype
, excvalue
, tb
)
265 return (exctype
, excvalue
, tb
)
266 return (exctype
, excvalue
, newtb
)
268 def fail(self
, msg
=None):
269 """Fail immediately, with the given message."""
270 raise self
.failureException
, msg
272 def failIf(self
, expr
, msg
=None):
273 "Fail the test if the expression is true."
274 if expr
: raise self
.failureException
, msg
276 def failUnless(self
, expr
, msg
=None):
277 """Fail the test unless the expression is true."""
278 if not expr
: raise self
.failureException
, msg
280 def failUnlessRaises(self
, excClass
, callableObj
, *args
, **kwargs
):
281 """Fail unless an exception of class excClass is thrown
282 by callableObj when invoked with arguments args and keyword
283 arguments kwargs. If a different type of exception is
284 thrown, it will not be caught, and the test case will be
285 deemed to have suffered an error, exactly as for an
286 unexpected exception.
289 callableObj(*args
, **kwargs
)
293 if hasattr(excClass
,'__name__'): excName
= excClass
.__name
__
294 else: excName
= str(excClass
)
295 raise self
.failureException
, excName
297 def failUnlessEqual(self
, first
, second
, msg
=None):
298 """Fail if the two objects are unequal as determined by the '=='
301 if not first
== second
:
302 raise self
.failureException
, \
303 (msg
or '%s != %s' % (`first`
, `second`
))
305 def failIfEqual(self
, first
, second
, msg
=None):
306 """Fail if the two objects are equal as determined by the '=='
310 raise self
.failureException
, \
311 (msg
or '%s == %s' % (`first`
, `second`
))
313 def failUnlessAlmostEqual(self
, first
, second
, places
=7, msg
=None):
314 """Fail if the two objects are unequal as determined by their
315 difference rounded to the given number of decimal places
316 (default 7) and comparing to zero.
318 Note that decimal places (from zero) is usually not the same
319 as significant digits (measured from the most signficant digit).
321 if round(second
-first
, places
) != 0:
322 raise self
.failureException
, \
323 (msg
or '%s != %s within %s places' % (`first`
, `second`
, `places`
))
325 def failIfAlmostEqual(self
, first
, second
, places
=7, msg
=None):
326 """Fail if the two objects are equal as determined by their
327 difference rounded to the given number of decimal places
328 (default 7) and comparing to zero.
330 Note that decimal places (from zero) is usually not the same
331 as significant digits (measured from the most signficant digit).
333 if round(second
-first
, places
) == 0:
334 raise self
.failureException
, \
335 (msg
or '%s == %s within %s places' % (`first`
, `second`
, `places`
))
337 assertEqual
= assertEquals
= failUnlessEqual
339 assertNotEqual
= assertNotEquals
= failIfEqual
341 assertAlmostEqual
= assertAlmostEquals
= failUnlessAlmostEqual
343 assertNotAlmostEqual
= assertNotAlmostEquals
= failIfAlmostEqual
345 assertRaises
= failUnlessRaises
352 """A test suite is a composite test consisting of a number of TestCases.
354 For use, create an instance of TestSuite, then add test case instances.
355 When all tests have been added, the suite can be passed to a test
356 runner, such as TextTestRunner. It will run the individual test cases
357 in the order in which they were added, aggregating the results. When
358 subclassing, do not forget to call the base class constructor.
360 def __init__(self
, tests
=()):
365 return "<%s tests=%s>" % (_strclass(self
.__class
__), self
._tests
)
369 def countTestCases(self
):
371 for test
in self
._tests
:
372 cases
= cases
+ test
.countTestCases()
375 def addTest(self
, test
):
376 self
._tests
.append(test
)
378 def addTests(self
, tests
):
382 def run(self
, result
):
385 def __call__(self
, result
):
386 for test
in self
._tests
:
387 if result
.shouldStop
:
393 """Run the tests without collecting errors in a TestResult"""
394 for test
in self
._tests
: test
.debug()
397 class FunctionTestCase(TestCase
):
398 """A test case that wraps a test function.
400 This is useful for slipping pre-existing test functions into the
401 PyUnit framework. Optionally, set-up and tidy-up functions can be
402 supplied. As with TestCase, the tidy-up ('tearDown') function will
403 always be called if the set-up ('setUp') function ran successfully.
406 def __init__(self
, testFunc
, setUp
=None, tearDown
=None,
408 TestCase
.__init
__(self
)
409 self
.__setUpFunc
= setUp
410 self
.__tearDownFunc
= tearDown
411 self
.__testFunc
= testFunc
412 self
.__description
= description
415 if self
.__setUpFunc
is not None:
419 if self
.__tearDownFunc
is not None:
420 self
.__tearDownFunc
()
426 return self
.__testFunc
.__name
__
429 return "%s (%s)" % (_strclass(self
.__class
__), self
.__testFunc
.__name
__)
432 return "<%s testFunc=%s>" % (_strclass(self
.__class
__), self
.__testFunc
)
434 def shortDescription(self
):
435 if self
.__description
is not None: return self
.__description
436 doc
= self
.__testFunc
.__doc
__
437 return doc
and string
.strip(string
.split(doc
, "\n")[0]) or None
441 ##############################################################################
442 # Locating and loading tests
443 ##############################################################################
446 """This class is responsible for loading tests according to various
447 criteria and returning them wrapped in a Test
449 testMethodPrefix
= 'test'
450 sortTestMethodsUsing
= cmp
451 suiteClass
= TestSuite
453 def loadTestsFromTestCase(self
, testCaseClass
):
454 """Return a suite of all tests cases contained in testCaseClass"""
455 return self
.suiteClass(map(testCaseClass
,
456 self
.getTestCaseNames(testCaseClass
)))
458 def loadTestsFromModule(self
, module
):
459 """Return a suite of all tests cases contained in the given module"""
461 for name
in dir(module
):
462 obj
= getattr(module
, name
)
463 if (isinstance(obj
, (type, types
.ClassType
)) and
464 issubclass(obj
, TestCase
)):
465 tests
.append(self
.loadTestsFromTestCase(obj
))
466 return self
.suiteClass(tests
)
468 def loadTestsFromName(self
, name
, module
=None):
469 """Return a suite of all tests cases given a string specifier.
471 The name may resolve either to a module, a test case class, a
472 test method within a test case class, or a callable object which
473 returns a TestCase or TestSuite instance.
475 The method optionally resolves the names relative to a given module.
477 parts
= string
.split(name
, '.')
480 raise ValueError, "incomplete test name: %s" % name
482 parts_copy
= parts
[:]
485 module
= __import__(string
.join(parts_copy
,'.'))
489 if not parts_copy
: raise
493 obj
= getattr(obj
, part
)
496 if type(obj
) == types
.ModuleType
:
497 return self
.loadTestsFromModule(obj
)
498 elif (isinstance(obj
, (type, types
.ClassType
)) and
499 issubclass(obj
, unittest
.TestCase
)):
500 return self
.loadTestsFromTestCase(obj
)
501 elif type(obj
) == types
.UnboundMethodType
:
502 return obj
.im_class(obj
.__name
__)
505 if not isinstance(test
, unittest
.TestCase
) and \
506 not isinstance(test
, unittest
.TestSuite
):
508 "calling %s returned %s, not a test" % (obj
,test
)
511 raise ValueError, "don't know how to make test from: %s" % obj
513 def loadTestsFromNames(self
, names
, module
=None):
514 """Return a suite of all tests cases found using the given sequence
515 of string specifiers. See 'loadTestsFromName()'.
519 suites
.append(self
.loadTestsFromName(name
, module
))
520 return self
.suiteClass(suites
)
522 def getTestCaseNames(self
, testCaseClass
):
523 """Return a sorted sequence of method names found within testCaseClass
525 testFnNames
= filter(lambda n
,p
=self
.testMethodPrefix
: n
[:len(p
)] == p
,
527 for baseclass
in testCaseClass
.__bases
__:
528 for testFnName
in self
.getTestCaseNames(baseclass
):
529 if testFnName
not in testFnNames
: # handle overridden methods
530 testFnNames
.append(testFnName
)
531 if self
.sortTestMethodsUsing
:
532 testFnNames
.sort(self
.sortTestMethodsUsing
)
537 defaultTestLoader
= TestLoader()
540 ##############################################################################
541 # Patches for old functions: these functions should be considered obsolete
542 ##############################################################################
544 def _makeLoader(prefix
, sortUsing
, suiteClass
=None):
545 loader
= TestLoader()
546 loader
.sortTestMethodsUsing
= sortUsing
547 loader
.testMethodPrefix
= prefix
548 if suiteClass
: loader
.suiteClass
= suiteClass
551 def getTestCaseNames(testCaseClass
, prefix
, sortUsing
=cmp):
552 return _makeLoader(prefix
, sortUsing
).getTestCaseNames(testCaseClass
)
554 def makeSuite(testCaseClass
, prefix
='test', sortUsing
=cmp, suiteClass
=TestSuite
):
555 return _makeLoader(prefix
, sortUsing
, suiteClass
).loadTestsFromTestCase(testCaseClass
)
557 def findTestCases(module
, prefix
='test', sortUsing
=cmp, suiteClass
=TestSuite
):
558 return _makeLoader(prefix
, sortUsing
, suiteClass
).loadTestsFromModule(module
)
561 ##############################################################################
563 ##############################################################################
565 class _WritelnDecorator
:
566 """Used to decorate file-like objects with a handy 'writeln' method"""
567 def __init__(self
,stream
):
570 def __getattr__(self
, attr
):
571 return getattr(self
.stream
,attr
)
573 def writeln(self
, arg
=None):
574 if arg
: self
.write(arg
)
575 self
.write('\n') # text-mode streams translate to \r\n if needed
578 class _TextTestResult(TestResult
):
579 """A test result class that can print formatted text results to a stream.
581 Used by TextTestRunner.
583 separator1
= '=' * 70
584 separator2
= '-' * 70
586 def __init__(self
, stream
, descriptions
, verbosity
):
587 TestResult
.__init
__(self
)
589 self
.showAll
= verbosity
> 1
590 self
.dots
= verbosity
== 1
591 self
.descriptions
= descriptions
593 def getDescription(self
, test
):
594 if self
.descriptions
:
595 return test
.shortDescription() or str(test
)
599 def startTest(self
, test
):
600 TestResult
.startTest(self
, test
)
602 self
.stream
.write(self
.getDescription(test
))
603 self
.stream
.write(" ... ")
605 def addSuccess(self
, test
):
606 TestResult
.addSuccess(self
, test
)
608 self
.stream
.writeln("ok")
610 self
.stream
.write('.')
612 def addError(self
, test
, err
):
613 TestResult
.addError(self
, test
, err
)
615 self
.stream
.writeln("ERROR")
617 self
.stream
.write('E')
619 def addFailure(self
, test
, err
):
620 TestResult
.addFailure(self
, test
, err
)
622 self
.stream
.writeln("FAIL")
624 self
.stream
.write('F')
626 def printErrors(self
):
627 if self
.dots
or self
.showAll
:
628 self
.stream
.writeln()
629 self
.printErrorList('ERROR', self
.errors
)
630 self
.printErrorList('FAIL', self
.failures
)
632 def printErrorList(self
, flavour
, errors
):
633 for test
, err
in errors
:
634 self
.stream
.writeln(self
.separator1
)
635 self
.stream
.writeln("%s: %s" % (flavour
,self
.getDescription(test
)))
636 self
.stream
.writeln(self
.separator2
)
637 self
.stream
.writeln("%s" % err
)
640 class TextTestRunner
:
641 """A test runner class that displays results in textual form.
643 It prints out the names of tests as they are run, errors as they
644 occur, and a summary of the results at the end of the test run.
646 def __init__(self
, stream
=sys
.stderr
, descriptions
=1, verbosity
=1):
647 self
.stream
= _WritelnDecorator(stream
)
648 self
.descriptions
= descriptions
649 self
.verbosity
= verbosity
651 def _makeResult(self
):
652 return _TextTestResult(self
.stream
, self
.descriptions
, self
.verbosity
)
655 "Run the given test case or test suite."
656 result
= self
._makeResult
()
657 startTime
= time
.time()
659 stopTime
= time
.time()
660 timeTaken
= float(stopTime
- startTime
)
662 self
.stream
.writeln(result
.separator2
)
663 run
= result
.testsRun
664 self
.stream
.writeln("Ran %d test%s in %.3fs" %
665 (run
, run
!= 1 and "s" or "", timeTaken
))
666 self
.stream
.writeln()
667 if not result
.wasSuccessful():
668 self
.stream
.write("FAILED (")
669 failed
, errored
= map(len, (result
.failures
, result
.errors
))
671 self
.stream
.write("failures=%d" % failed
)
673 if failed
: self
.stream
.write(", ")
674 self
.stream
.write("errors=%d" % errored
)
675 self
.stream
.writeln(")")
677 self
.stream
.writeln("OK")
682 ##############################################################################
683 # Facilities for running tests from the command line
684 ##############################################################################
687 """A command-line program that runs a set of tests; this is primarily
688 for making test modules conveniently executable.
691 Usage: %(progName)s [options] [test] [...]
694 -h, --help Show this message
695 -v, --verbose Verbose output
696 -q, --quiet Minimal output
699 %(progName)s - run default set of tests
700 %(progName)s MyTestSuite - run suite 'MyTestSuite'
701 %(progName)s MyTestCase.testSomething - run MyTestCase.testSomething
702 %(progName)s MyTestCase - run all 'test*' test methods
705 def __init__(self
, module
='__main__', defaultTest
=None,
706 argv
=None, testRunner
=None, testLoader
=defaultTestLoader
):
707 if type(module
) == type(''):
708 self
.module
= __import__(module
)
709 for part
in string
.split(module
,'.')[1:]:
710 self
.module
= getattr(self
.module
, part
)
716 self
.defaultTest
= defaultTest
717 self
.testRunner
= testRunner
718 self
.testLoader
= testLoader
719 self
.progName
= os
.path
.basename(argv
[0])
723 def usageExit(self
, msg
=None):
725 print self
.USAGE
% self
.__dict
__
728 def parseArgs(self
, argv
):
731 options
, args
= getopt
.getopt(argv
[1:], 'hHvq',
732 ['help','verbose','quiet'])
733 for opt
, value
in options
:
734 if opt
in ('-h','-H','--help'):
736 if opt
in ('-q','--quiet'):
738 if opt
in ('-v','--verbose'):
740 if len(args
) == 0 and self
.defaultTest
is None:
741 self
.test
= self
.testLoader
.loadTestsFromModule(self
.module
)
744 self
.testNames
= args
746 self
.testNames
= (self
.defaultTest
,)
748 except getopt
.error
, msg
:
751 def createTests(self
):
752 self
.test
= self
.testLoader
.loadTestsFromNames(self
.testNames
,
756 if self
.testRunner
is None:
757 self
.testRunner
= TextTestRunner(verbosity
=self
.verbosity
)
758 result
= self
.testRunner
.run(self
.test
)
759 sys
.exit(not result
.wasSuccessful())
764 ##############################################################################
765 # Executing this module from the command line
766 ##############################################################################
768 if __name__
== "__main__":