4
Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
5
Smalltalk testing framework.
7
This module contains the core framework classes that form the basis of
8
specific test cases and suites (TestCase, TestSuite etc.), and also a
9
text-based utility class for running the tests and reporting the results
16
class IntegerArithmenticTestCase(unittest.TestCase):
17
def testAdd(self): ## test method names begin 'test*'
18
self.assertEquals((1 + 2), 3)
19
self.assertEquals(0 + 1, 1)
20
def testMultiply(self):
21
self.assertEquals((0 * 10), 0)
22
self.assertEquals((5 * 8), 40)
24
if __name__ == '__main__':
27
Further information is available in the bundled documentation, and from
29
http://pyunit.sourceforge.net/
31
Copyright (c) 1999-2003 Steve Purcell
32
This module is free software, and you may redistribute it and/or modify
33
it under the same terms as Python itself, so long as this copyright message
34
and disclaimer are retained in their original form.
36
IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
37
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
38
THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
41
THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
42
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
43
PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
44
AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
45
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
48
__author__ = "Steve Purcell"
49
__email__ = "stephen_purcell at yahoo dot com"
50
__version__ = "#Revision: 1.63 $"[11:-2]
62
"""Return -1 if x < y, 0 if x == y and 1 if x > y"""
63
return (x > y) - (x < y)
64
cmp = staticmethod(cmp)
68
except AttributeError:
71
class_types = (type, types.ClassType)
79
except AttributeError:
89
return sys.exc_info()[1]
91
##############################################################################
92
# Exported classes and functions
93
##############################################################################
94
__all__ = ['TestResult', 'TestCase', 'TestSuite', 'TextTestRunner',
95
'TestLoader', 'FunctionTestCase', 'main', 'defaultTestLoader']
97
# Expose obsolete functions for backwards compatibility
98
__all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
103
def _sort_using_key(seq, key_func):
104
deco = [ (key_func(word), i, word) for i, word in enumerate(seq) ]
106
new_words = [ word for _, _, word in deco ]
110
##############################################################################
111
# Backward compatibility
112
##############################################################################
113
#if sys.version_info[:2] < (2, 2):
115
# def isinstance(obj, clsinfo):
117
# if type(clsinfo) in (tuple, list):
118
# for cls in clsinfo:
119
# if cls is type: cls = types.ClassType
120
# if __builtin__.isinstance(obj, cls):
123
# else: return __builtin__.isinstance(obj, clsinfo)
126
##############################################################################
127
# Test framework core
128
##############################################################################
130
# All classes defined herein are 'new-style' classes, allowing use of 'super()'
134
return "%s.%s" % (cls.__module__, cls.__name__)
139
"""Holder for test result information.
141
Test results are automatically managed by the TestCase and TestSuite
142
classes, and do not need to be explicitly manipulated by writers of tests.
144
Each instance holds the total number of tests run, and collections of
145
failures and errors that occurred among those test runs. The collections
146
contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
147
formatted traceback of the error that occurred.
155
def startTest(self, test):
156
"Called when the given test is about to be run"
157
self.testsRun = self.testsRun + 1
159
def stopTest(self, test):
160
"Called when the given test has been run"
163
def addError(self, test, err):
164
"""Called when an error has occurred. 'err' is a tuple of values as
165
returned by sys.exc_info().
167
self.errors.append((test, self._exc_info_to_string(err, test)))
169
def addFailure(self, test, err):
170
"""Called when an error has occurred. 'err' is a tuple of values as
171
returned by sys.exc_info()."""
172
self.failures.append((test, self._exc_info_to_string(err, test)))
174
def addSuccess(self, test):
175
"Called when a test has completed successfully"
178
def wasSuccessful(self):
179
"Tells whether or not this result was a success"
180
return len(self.failures) == len(self.errors) == 0
183
"Indicates that the tests should be aborted"
184
self.shouldStop = True
186
def _exc_info_to_string(self, err, test):
187
"""Converts a sys.exc_info()-style tuple of values into a string."""
188
exctype, value, tb = err
189
# Skip test runner traceback levels
190
while tb and self._is_relevant_tb_level(tb):
192
if exctype is test.failureException:
193
# Skip assert*() traceback levels
194
length = self._count_relevant_tb_levels(tb)
195
return ''.join(traceback.format_exception(exctype, value, tb, length))
196
return ''.join(traceback.format_exception(exctype, value, tb))
198
def _is_relevant_tb_level(self, tb):
199
return '__unittest' in tb.tb_frame.f_globals
201
def _count_relevant_tb_levels(self, tb):
203
while tb and not self._is_relevant_tb_level(tb):
209
return "<%s run=%i errors=%i failures=%i>" % \
210
(_strclass(self.__class__), self.testsRun, len(self.errors),
214
"""A class whose instances are single test cases.
216
By default, the test code itself should be placed in a method named
219
If the fixture may be used for many test cases, create as
220
many test methods as are needed. When instantiating such a TestCase
221
subclass, specify in the constructor arguments the name of the test method
222
that the instance is to execute.
224
Test authors should subclass TestCase for their own tests. Construction
225
and deconstruction of the test's environment ('fixture') can be
226
implemented by overriding the 'setUp' and 'tearDown' methods respectively.
228
If it is necessary to override the __init__ method, the base class
229
__init__ method must always be called. It is important that subclasses
230
should not change the signature of their __init__ method, since instances
231
of the classes are instantiated automatically by parts of the framework
235
# This attribute determines which exception will be raised when
236
# the instance's assertion methods fail; test methods raising this
237
# exception will be deemed to have 'failed' rather than 'errored'
239
failureException = AssertionError
241
def __init__(self, methodName='runTest'):
242
"""Create an instance of the class that will use the named test
243
method when executed. Raises a ValueError if the instance does
244
not have a method with the specified name.
247
self._testMethodName = methodName
248
testMethod = getattr(self, methodName)
249
self._testMethodDoc = testMethod.__doc__
250
except AttributeError:
251
raise ValueError( "no such test method in %s: %s" % \
252
(self.__class__, methodName))
255
"Hook method for setting up the test fixture before exercising it."
259
"Hook method for deconstructing the test fixture after testing it."
262
def countTestCases(self):
265
def defaultTestResult(self):
268
def shortDescription(self):
269
"""Returns a one-line description of the test, or None if no
270
description has been provided.
272
The default implementation of this method returns the first line of
273
the specified test method's docstring.
275
doc = self._testMethodDoc
276
return doc and doc.split("\n")[0].strip() or None
279
return "%s.%s" % (_strclass(self.__class__), self._testMethodName)
282
return "%s (%s)" % (self._testMethodName, _strclass(self.__class__))
285
return "<%s testMethod=%s>" % \
286
(_strclass(self.__class__), self._testMethodName)
288
def run(self, result=None):
289
if result is None: result = self.defaultTestResult()
290
result.startTest(self)
291
testMethod = getattr(self, self._testMethodName)
295
except KeyboardInterrupt:
298
result.addError(self, self._exc_info())
305
except self.failureException:
306
result.addFailure(self, self._exc_info())
307
except KeyboardInterrupt:
310
result.addError(self, self._exc_info())
314
except KeyboardInterrupt:
317
result.addError(self, self._exc_info())
319
if ok: result.addSuccess(self)
321
result.stopTest(self)
323
def __call__(self, *args, **kwds):
324
return self.run(*args, **kwds)
327
"""Run the test without collecting errors in a TestResult"""
329
getattr(self, self._testMethodName)()
333
"""Return a version of sys.exc_info() with the traceback frame
334
minimised; usually the top level of the traceback frame is not
337
exctype, excvalue, tb = sys.exc_info()
338
if sys.platform[:4] == 'java': ## tracebacks look different in Jython
339
return (exctype, excvalue, tb)
340
return (exctype, excvalue, tb)
342
def fail(self, msg=None):
343
"""Fail immediately, with the given message."""
344
raise self.failureException( msg)
346
def failIf(self, expr, msg=None):
347
"Fail the test if the expression is true."
348
if expr: raise self.failureException( msg)
350
def failUnless(self, expr, msg=None):
351
"""Fail the test unless the expression is true."""
352
if not expr: raise self.failureException( msg)
354
def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
355
"""Fail unless an exception of class excClass is thrown
356
by callableObj when invoked with arguments args and keyword
357
arguments kwargs. If a different type of exception is
358
thrown, it will not be caught, and the test case will be
359
deemed to have suffered an error, exactly as for an
360
unexpected exception.
363
callableObj(*args, **kwargs)
367
if hasattr(excClass,'__name__'): excName = excClass.__name__
368
else: excName = str(excClass)
369
raise self.failureException( "%s not raised" % excName)
371
def failUnlessEqual(self, first, second, msg=None):
372
"""Fail if the two objects are unequal as determined by the '=='
375
if not first == second:
376
raise self.failureException(
377
(msg or '%r != %r' % (first, second)))
379
def failIfEqual(self, first, second, msg=None):
380
"""Fail if the two objects are equal as determined by the '=='
384
raise self.failureException(
385
(msg or '%r == %r' % (first, second)))
387
def failUnlessAlmostEqual(self, first, second, places=7, msg=None):
388
"""Fail if the two objects are unequal as determined by their
389
difference rounded to the given number of decimal places
390
(default 7) and comparing to zero.
392
Note that decimal places (from zero) are usually not the same
393
as significant digits (measured from the most signficant digit).
395
if round(second-first, places) != 0:
396
raise self.failureException(
397
(msg or '%r != %r within %r places' % (first, second, places)))
399
def failIfAlmostEqual(self, first, second, places=7, msg=None):
400
"""Fail if the two objects are equal as determined by their
401
difference rounded to the given number of decimal places
402
(default 7) and comparing to zero.
404
Note that decimal places (from zero) are usually not the same
405
as significant digits (measured from the most signficant digit).
407
if round(second-first, places) == 0:
408
raise self.failureException(
409
(msg or '%r == %r within %r places' % (first, second, places)))
411
# Synonyms for assertion methods
413
assertEqual = assertEquals = failUnlessEqual
415
assertNotEqual = assertNotEquals = failIfEqual
417
assertAlmostEqual = assertAlmostEquals = failUnlessAlmostEqual
419
assertNotAlmostEqual = assertNotAlmostEquals = failIfAlmostEqual
421
assertRaises = failUnlessRaises
423
assert_ = assertTrue = failUnless
430
"""A test suite is a composite test consisting of a number of TestCases.
432
For use, create an instance of TestSuite, then add test case instances.
433
When all tests have been added, the suite can be passed to a test
434
runner, such as TextTestRunner. It will run the individual test cases
435
in the order in which they were added, aggregating the results. When
436
subclassing, do not forget to call the base class constructor.
439
def __init__(self, tests=()):
444
return "<%s tests=%s>" % (_strclass(self.__class__), self._tests)
449
return iter(self._tests)
451
def countTestCases(self):
453
for test in self._tests:
454
cases += test.countTestCases()
457
def addTest(self, test):
459
if not callable(test):
460
raise TypeError("the test to add must be callable")
461
if (isinstance(test, class_types) and
462
issubclass(test, (TestCase, TestSuite))):
463
raise TypeError("TestCases and TestSuites must be instantiated "
464
"before passing them to addTest()")
465
self._tests.append(test)
467
def addTests(self, tests):
468
if isinstance(tests, basestring):
469
raise TypeError("tests must be an iterable of tests, not a string")
473
def run(self, result):
474
for test in self._tests:
475
if result.shouldStop:
480
def __call__(self, *args, **kwds):
481
return self.run(*args, **kwds)
484
"""Run the tests without collecting errors in a TestResult"""
485
for test in self._tests: test.debug()
488
class FunctionTestCase(TestCase):
489
"""A test case that wraps a test function.
491
This is useful for slipping pre-existing test functions into the
492
PyUnit framework. Optionally, set-up and tidy-up functions can be
493
supplied. As with TestCase, the tidy-up ('tearDown') function will
494
always be called if the set-up ('setUp') function ran successfully.
497
def __init__(self, testFunc, setUp=None, tearDown=None,
499
TestCase.__init__(self)
500
self.__setUpFunc = setUp
501
self.__tearDownFunc = tearDown
502
self.__testFunc = testFunc
503
self.__description = description
506
if self.__setUpFunc is not None:
510
if self.__tearDownFunc is not None:
511
self.__tearDownFunc()
517
return self.__testFunc.__name__
520
return "%s (%s)" % (_strclass(self.__class__), self.__testFunc.__name__)
523
return "<%s testFunc=%s>" % (_strclass(self.__class__), self.__testFunc)
525
def shortDescription(self):
526
if self.__description is not None: return self.__description
527
doc = self.__testFunc.__doc__
528
return doc and doc.split("\n")[0].strip() or None
530
##############################################################################
531
# Locating and loading tests
532
##############################################################################
535
'Convert a cmp= function into a key= function'
537
def __init__(self, obj, *args):
539
def __lt__(self, other):
540
return mycmp(self.obj, other.obj) == -1
543
def three_way_cmp(x, y):
544
"""Return -1 if x < y, 0 if x == y and 1 if x > y"""
545
return (x > y) - (x < y)
548
"""This class is responsible for loading tests according to various
549
criteria and returning them wrapped in a Test
551
testMethodPrefix = 'test'
552
sortTestMethodsUsing = cmp
553
suiteClass = TestSuite
555
def loadTestsFromTestCase(self, testCaseClass):
556
"""Return a suite of all tests cases contained in testCaseClass"""
557
if issubclass(testCaseClass, TestSuite):
558
raise TypeError("Test cases should not be derived from TestSuite. Maybe you meant to derive from TestCase?")
559
testCaseNames = self.getTestCaseNames(testCaseClass)
560
if not testCaseNames and hasattr(testCaseClass, 'runTest'):
561
testCaseNames = ['runTest']
562
return self.suiteClass([testCaseClass(n) for n in testCaseNames])
564
def loadTestsFromModule(self, module):
565
"""Return a suite of all tests cases contained in the given module"""
567
for name in dir(module):
568
obj = getattr(module, name)
569
if (isinstance(obj, class_types) and
570
issubclass(obj, TestCase)):
571
tests.append(self.loadTestsFromTestCase(obj))
572
return self.suiteClass(tests)
574
def loadTestsFromName(self, name, module=None):
575
"""Return a suite of all tests cases given a string specifier.
577
The name may resolve either to a module, a test case class, a
578
test method within a test case class, or a callable object which
579
returns a TestCase or TestSuite instance.
581
The method optionally resolves the names relative to a given module.
583
parts = name.split('.')
585
parts_copy = parts[:]
588
module = __import__('.'.join(parts_copy))
592
if not parts_copy: raise
596
parent, obj = obj, getattr(obj, part)
598
if type(obj) == types.ModuleType:
599
return self.loadTestsFromModule(obj)
600
elif (isinstance(obj, class_types) and
601
issubclass(obj, TestCase)):
602
return self.loadTestsFromTestCase(obj)
603
elif type(obj) == types.UnboundMethodType:
604
return parent(obj.__name__)
605
elif isinstance(obj, TestSuite):
609
if not isinstance(test, (TestCase, TestSuite)):
611
"calling %s returned %s, not a test" % (obj,test))
614
raise ValueError( "don't know how to make test from: %s" % obj)
616
def loadTestsFromNames(self, names, module=None):
617
"""Return a suite of all tests cases found using the given sequence
618
of string specifiers. See 'loadTestsFromName()'.
620
suites = [self.loadTestsFromName(name, module) for name in names]
621
return self.suiteClass(suites)
623
def getTestCaseNames(self, testCaseClass):
624
"""Return a sorted sequence of method names found within testCaseClass
626
def isTestMethod(attrname, testCaseClass=testCaseClass, prefix=self.testMethodPrefix):
627
return attrname.startswith(prefix) and callable(getattr(testCaseClass, attrname))
628
testFnNames = list(filter(isTestMethod, dir(testCaseClass)))
629
for baseclass in testCaseClass.__bases__:
630
for testFnName in self.getTestCaseNames(baseclass):
631
if testFnName not in testFnNames: # handle overridden methods
632
testFnNames.append(testFnName)
633
if self.sortTestMethodsUsing:
634
#testFnNames.sort(key=CmpToKey(self.sortTestMethodsUsing))
635
testFnNames = _sort_using_key(testFnNames, CmpToKey(self.sortTestMethodsUsing))
642
defaultTestLoader = TestLoader()
645
##############################################################################
646
# Patches for old functions: these functions should be considered obsolete
647
##############################################################################
649
def _makeLoader(prefix, sortUsing, suiteClass=None):
650
loader = TestLoader()
651
loader.sortTestMethodsUsing = sortUsing
652
loader.testMethodPrefix = prefix
653
if suiteClass: loader.suiteClass = suiteClass
656
def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
657
return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
659
def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
660
return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
662
def findTestCases(module, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
663
return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
666
##############################################################################
668
##############################################################################
670
class _WritelnDecorator:
671
"""Used to decorate file-like objects with a handy 'writeln' method"""
672
def __init__(self,stream):
675
def __getattr__(self, attr):
676
return getattr(self.stream,attr)
678
def writeln(self, arg=None):
679
if arg: self.write(arg)
680
self.write('\n') # text-mode streams translate to \r\n if needed
683
class _TextTestResult(TestResult):
684
"""A test result class that can print formatted text results to a stream.
686
Used by TextTestRunner.
688
separator1 = '=' * 70
689
separator2 = '-' * 70
691
def __init__(self, stream, descriptions, verbosity):
692
TestResult.__init__(self)
694
self.showAll = verbosity > 1
695
self.dots = verbosity == 1
696
self.descriptions = descriptions
698
def getDescription(self, test):
699
if self.descriptions:
700
return test.shortDescription() or str(test)
704
def startTest(self, test):
705
TestResult.startTest(self, test)
707
self.stream.write(self.getDescription(test))
708
self.stream.write(" ... ")
710
def addSuccess(self, test):
711
TestResult.addSuccess(self, test)
713
self.stream.writeln("ok")
715
self.stream.write('.')
717
def addError(self, test, err):
718
TestResult.addError(self, test, err)
720
self.stream.writeln("ERROR")
722
self.stream.write('E')
724
def addFailure(self, test, err):
725
TestResult.addFailure(self, test, err)
727
self.stream.writeln("FAIL")
729
self.stream.write('F')
731
def printErrors(self):
732
if self.dots or self.showAll:
733
self.stream.writeln()
734
self.printErrorList('ERROR', self.errors)
735
self.printErrorList('FAIL', self.failures)
737
def printErrorList(self, flavour, errors):
738
for test, err in errors:
739
self.stream.writeln(self.separator1)
740
self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
741
self.stream.writeln(self.separator2)
742
self.stream.writeln("%s" % err)
745
class TextTestRunner:
746
"""A test runner class that displays results in textual form.
748
It prints out the names of tests as they are run, errors as they
749
occur, and a summary of the results at the end of the test run.
751
def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1):
752
self.stream = _WritelnDecorator(stream)
753
self.descriptions = descriptions
754
self.verbosity = verbosity
756
def _makeResult(self):
757
return _TextTestResult(self.stream, self.descriptions, self.verbosity)
760
"Run the given test case or test suite."
761
result = self._makeResult()
762
startTime = time.time()
764
stopTime = time.time()
765
timeTaken = stopTime - startTime
767
self.stream.writeln(result.separator2)
768
run = result.testsRun
769
self.stream.writeln("Ran %d test%s in %.3fs" %
770
(run, run != 1 and "s" or "", timeTaken))
771
self.stream.writeln()
772
if not result.wasSuccessful():
773
self.stream.write("FAILED (")
774
failed, errored = len(result.failures), len(result.errors)
776
self.stream.write("failures=%d" % failed)
778
if failed: self.stream.write(", ")
779
self.stream.write("errors=%d" % errored)
780
self.stream.writeln(")")
782
self.stream.writeln("OK")
787
##############################################################################
788
# Facilities for running tests from the command line
789
##############################################################################
792
"""A command-line program that runs a set of tests; this is primarily
793
for making test modules conveniently executable.
796
Usage: %(progName)s [options] [test] [...]
799
-h, --help Show this message
800
-v, --verbose Verbose output
801
-q, --quiet Minimal output
804
%(progName)s - run default set of tests
805
%(progName)s MyTestSuite - run suite 'MyTestSuite'
806
%(progName)s MyTestCase.testSomething - run MyTestCase.testSomething
807
%(progName)s MyTestCase - run all 'test*' test methods
810
def __init__(self, module='__main__', defaultTest=None,
811
argv=None, testRunner=None, testLoader=defaultTestLoader):
812
if type(module) == type(''):
813
self.module = __import__(module)
814
for part in module.split('.')[1:]:
815
self.module = getattr(self.module, part)
821
self.defaultTest = defaultTest
822
self.testRunner = testRunner
823
self.testLoader = testLoader
824
self.progName = os.path.basename(argv[0])
828
def usageExit(self, msg=None):
830
print (self.USAGE % self.__dict__)
833
def parseArgs(self, argv):
836
options, args = getopt.getopt(argv[1:], 'hHvq',
837
['help','verbose','quiet'])
838
for opt, value in options:
839
if opt in ('-h','-H','--help'):
841
if opt in ('-q','--quiet'):
843
if opt in ('-v','--verbose'):
845
if len(args) == 0 and self.defaultTest is None:
846
self.test = self.testLoader.loadTestsFromModule(self.module)
849
self.testNames = args
851
self.testNames = (self.defaultTest,)
857
def createTests(self):
858
self.test = self.testLoader.loadTestsFromNames(self.testNames,
862
if self.testRunner is None:
863
self.testRunner = TextTestRunner(verbosity=self.verbosity)
864
result = self.testRunner.run(self.test)
865
sys.exit(not result.wasSuccessful())
869
##############################################################################
870
# Executing this module from the command line
871
##############################################################################
873
if __name__ == "__main__":