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 print 'hi'
49 __author__ = "Steve Purcell"
50 __email__ = "stephen_purcell at yahoo dot com"
51 __version__ = "$Revision: 1.1 $"[11:-2]
53 import time
54 import sys
55 import traceback
56 import string
57 import os
58 import types
60 ##############################################################################
61 # Test framework core
62 ##############################################################################
64 class TestResult:
65 """Holder for test result information.
67 Test results are automatically managed by the TestCase and TestSuite
68 classes, and do not need to be explicitly manipulated by writers of tests.
70 Each instance holds the total number of tests run, and collections of
71 failures and errors that occurred among those test runs. The collections
72 contain tuples of (testcase, exceptioninfo), where exceptioninfo is a
73 tuple of values as returned by sys.exc_info().
74 """
75 def __init__(self):
76 self.failures = []
77 self.errors = []
78 self.testsRun = 0
79 self.shouldStop = 0
81 def startTest(self, test):
82 "Called when the given test is about to be run"
83 self.testsRun = self.testsRun + 1
85 def stopTest(self, test):
86 "Called when the given test has been run"
87 pass
89 def addError(self, test, err):
90 "Called when an error has occurred"
91 self.errors.append((test, err))
93 def addFailure(self, test, err):
94 "Called when a failure has occurred"
95 self.failures.append((test, err))
97 def addSuccess(self, test):
98 "Called when a test has completed successfully"
99 pass
101 def wasSuccessful(self):
102 "Tells whether or not this result was a success"
103 return len(self.failures) == len(self.errors) == 0
105 def stop(self):
106 "Indicates that the tests should be aborted"
107 self.shouldStop = 1
109 def __repr__(self):
110 return "<%s run=%i errors=%i failures=%i>" % \
111 (self.__class__, self.testsRun, len(self.errors),
112 len(self.failures))
115 class TestCase:
116 """A class whose instances are single test cases.
118 By default, the test code itself should be placed in a method named
119 'runTest'.
121 If the fixture may be used for many test cases, create as
122 many test methods as are needed. When instantiating such a TestCase
123 subclass, specify in the constructor arguments the name of the test method
124 that the instance is to execute.
126 Test authors should subclass TestCase for their own tests. Construction
127 and deconstruction of the test's environment ('fixture') can be
128 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
130 If it is necessary to override the __init__ method, the base class
131 __init__ method must always be called. It is important that subclasses
132 should not change the signature of their __init__ method, since instances
133 of the classes are instantiated automatically by parts of the framework
134 in order to be run.
135 """
137 # This attribute determines which exception will be raised when
138 # the instance's assertion methods fail; test methods raising this
139 # exception will be deemed to have 'failed' rather than 'errored'
141 failureException = AssertionError
143 def __init__(self, methodName='runTest'):
144 """Create an instance of the class that will use the named test
145 method when executed. Raises a ValueError if the instance does
146 not have a method with the specified name.
147 """
148 try:
149 self.__testMethodName = methodName
150 testMethod = getattr(self, methodName)
151 self.__testMethodDoc = testMethod.__doc__
152 except AttributeError:
153 raise ValueError, "no such test method in %s: %s" % \
154 (self.__class__, methodName)
156 def setUp(self):
157 "Hook method for setting up the test fixture before exercising it."
158 pass
160 def tearDown(self):
161 "Hook method for deconstructing the test fixture after testing it."
162 pass
164 def countTestCases(self):
165 return 1
167 def defaultTestResult(self):
168 return TestResult()
170 def shortDescription(self):
171 """Returns a one-line description of the test, or None if no
172 description has been provided.
174 The default implementation of this method returns the first line of
175 the specified test method's docstring.
176 """
177 doc = self.__testMethodDoc
178 return doc and string.strip(string.split(doc, "\n")[0]) or None
180 def id(self):
181 return "%s.%s" % (self.__class__, self.__testMethodName)
183 def __str__(self):
184 return "%s (%s)" % (self.__testMethodName, self.__class__)
186 def __repr__(self):
187 return "<%s testMethod=%s>" % \
188 (self.__class__, self.__testMethodName)
190 def run(self, result=None):
191 return self(result)
193 def __call__(self, result=None):
194 if result is None: result = self.defaultTestResult()
195 result.startTest(self)
196 testMethod = getattr(self, self.__testMethodName)
197 try:
198 try:
199 self.setUp()
200 except:
201 result.addError(self,self.__exc_info())
202 return
204 ok = 0
205 try:
206 testMethod()
207 ok = 1
208 except self.failureException, e:
209 result.addFailure(self,self.__exc_info())
210 except:
211 result.addError(self,self.__exc_info())
213 try:
214 self.tearDown()
215 except:
216 result.addError(self,self.__exc_info())
217 ok = 0
218 if ok: result.addSuccess(self)
219 finally:
220 result.stopTest(self)
222 def debug(self):
223 """Run the test without collecting errors in a TestResult"""
224 self.setUp()
225 getattr(self, self.__testMethodName)()
226 self.tearDown()
228 def __exc_info(self):
229 """Return a version of sys.exc_info() with the traceback frame
230 minimised; usually the top level of the traceback frame is not
231 needed.
232 """
233 exctype, excvalue, tb = sys.exc_info()
234 if sys.platform[:4] == 'java': ## tracebacks look different in Jython
235 return (exctype, excvalue, tb)
236 newtb = tb.tb_next
237 if newtb is None:
238 return (exctype, excvalue, tb)
239 return (exctype, excvalue, newtb)
241 def fail(self, msg=None):
242 """Fail immediately, with the given message."""
243 raise self.failureException, msg
245 def failIf(self, expr, msg=None):
246 "Fail the test if the expression is true."
247 if expr: raise self.failureException, msg
249 def failUnless(self, expr, msg=None):
250 """Fail the test unless the expression is true."""
251 if not expr: raise self.failureException, msg
253 def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
254 """Fail unless an exception of class excClass is thrown
255 by callableObj when invoked with arguments args and keyword
256 arguments kwargs. If a different type of exception is
257 thrown, it will not be caught, and the test case will be
258 deemed to have suffered an error, exactly as for an
259 unexpected exception.
260 """
261 try:
262 apply(callableObj, args, kwargs)
263 except excClass:
264 return
265 else:
266 if hasattr(excClass,'__name__'): excName = excClass.__name__
267 else: excName = str(excClass)
268 raise self.failureException, excName
270 def failUnlessEqual(self, first, second, msg=None):
271 """Fail if the two objects are unequal as determined by the '!='
272 operator.
273 """
274 if first != second:
275 raise self.failureException, (msg or '%s != %s' % (first, second))
277 def failIfEqual(self, first, second, msg=None):
278 """Fail if the two objects are equal as determined by the '=='
279 operator.
280 """
281 if first == second:
282 raise self.failureException, (msg or '%s == %s' % (first, second))
284 assertEqual = assertEquals = failUnlessEqual
286 assertNotEqual = assertNotEquals = failIfEqual
288 assertRaises = failUnlessRaises
290 assert_ = failUnless
294 class TestSuite:
295 """A test suite is a composite test consisting of a number of TestCases.
297 For use, create an instance of TestSuite, then add test case instances.
298 When all tests have been added, the suite can be passed to a test
299 runner, such as TextTestRunner. It will run the individual test cases
300 in the order in which they were added, aggregating the results. When
301 subclassing, do not forget to call the base class constructor.
302 """
303 def __init__(self, tests=()):
304 self._tests = []
305 self.addTests(tests)
307 def __repr__(self):
308 return "<%s tests=%s>" % (self.__class__, self._tests)
310 __str__ = __repr__
312 def countTestCases(self):
313 cases = 0
314 for test in self._tests:
315 cases = cases + test.countTestCases()
316 return cases
318 def addTest(self, test):
319 self._tests.append(test)
321 def addTests(self, tests):
322 for test in tests:
323 self.addTest(test)
325 def run(self, result):
326 return self(result)
328 def __call__(self, result):
329 for test in self._tests:
330 if result.shouldStop:
331 break
332 test(result)
333 return result
335 def debug(self):
336 """Run the tests without collecting errors in a TestResult"""
337 for test in self._tests: test.debug()
340 class FunctionTestCase(TestCase):
341 """A test case that wraps a test function.
343 This is useful for slipping pre-existing test functions into the
344 PyUnit framework. Optionally, set-up and tidy-up functions can be
345 supplied. As with TestCase, the tidy-up ('tearDown') function will
346 always be called if the set-up ('setUp') function ran successfully.
347 """
349 def __init__(self, testFunc, setUp=None, tearDown=None,
350 description=None):
351 TestCase.__init__(self)
352 self.__setUpFunc = setUp
353 self.__tearDownFunc = tearDown
354 self.__testFunc = testFunc
355 self.__description = description
357 def setUp(self):
358 if self.__setUpFunc is not None:
359 self.__setUpFunc()
361 def tearDown(self):
362 if self.__tearDownFunc is not None:
363 self.__tearDownFunc()
365 def runTest(self):
366 self.__testFunc()
368 def id(self):
369 return self.__testFunc.__name__
371 def __str__(self):
372 return "%s (%s)" % (self.__class__, self.__testFunc.__name__)
374 def __repr__(self):
375 return "<%s testFunc=%s>" % (self.__class__, self.__testFunc)
377 def shortDescription(self):
378 if self.__description is not None: return self.__description
379 doc = self.__testFunc.__doc__
380 return doc and string.strip(string.split(doc, "\n")[0]) or None
384 ##############################################################################
385 # Locating and loading tests
386 ##############################################################################
388 class TestLoader:
389 """This class is responsible for loading tests according to various
390 criteria and returning them wrapped in a Test
391 """
392 testMethodPrefix = 'test'
393 sortTestMethodsUsing = cmp
394 suiteClass = TestSuite
396 def loadTestsFromTestCase(self, testCaseClass):
397 """Return a suite of all tests cases contained in testCaseClass"""
398 return self.suiteClass(map(testCaseClass,
399 self.getTestCaseNames(testCaseClass)))
401 def loadTestsFromModule(self, module):
402 """Return a suite of all tests cases contained in the given module"""
403 tests = []
404 for name in dir(module):
405 obj = getattr(module, name)
406 if type(obj) == types.ClassType and issubclass(obj, TestCase):
407 tests.append(self.loadTestsFromTestCase(obj))
408 return self.suiteClass(tests)
410 def loadTestsFromName(self, name, module=None):
411 """Return a suite of all tests cases given a string specifier.
413 The name may resolve either to a module, a test case class, a
414 test method within a test case class, or a callable object which
415 returns a TestCase or TestSuite instance.
417 The method optionally resolves the names relative to a given module.
418 """
419 parts = string.split(name, '.')
420 if module is None:
421 if not parts:
422 raise ValueError, "incomplete test name: %s" % name
423 else:
424 parts_copy = parts[:]
425 while parts_copy:
426 try:
427 module = __import__(string.join(parts_copy,'.'))
428 break
429 except ImportError:
430 del parts_copy[-1]
431 if not parts_copy: raise
432 parts = parts[1:]
433 obj = module
434 for part in parts:
435 obj = getattr(obj, part)
437 if type(obj) == types.ModuleType:
438 return self.loadTestsFromModule(obj)
439 elif type(obj) == types.ClassType and issubclass(obj, TestCase):
440 return self.loadTestsFromTestCase(obj)
441 elif type(obj) == types.UnboundMethodType:
442 return obj.im_class(obj.__name__)
443 elif callable(obj):
444 test = obj()
445 if not isinstance(test, TestCase) and \
446 not isinstance(test, TestSuite):
447 raise ValueError, \
448 "calling %s returned %s, not a test" % (obj,test)
449 return test
450 else:
451 raise ValueError, "don't know how to make test from: %s" % obj
453 def loadTestsFromNames(self, names, module=None):
454 """Return a suite of all tests cases found using the given sequence
455 of string specifiers. See 'loadTestsFromName()'.
456 """
457 suites = []
458 for name in names:
459 suites.append(self.loadTestsFromName(name, module))
460 return self.suiteClass(suites)
462 def getTestCaseNames(self, testCaseClass):
463 """Return a sorted sequence of method names found within testCaseClass
464 """
465 testFnNames = filter(lambda n,p=self.testMethodPrefix: n[:len(p)] == p,
466 dir(testCaseClass))
467 for baseclass in testCaseClass.__bases__:
468 for testFnName in self.getTestCaseNames(baseclass):
469 if testFnName not in testFnNames: # handle overridden methods
470 testFnNames.append(testFnName)
471 if self.sortTestMethodsUsing:
472 testFnNames.sort(self.sortTestMethodsUsing)
473 return testFnNames
477 defaultTestLoader = TestLoader()
480 ##############################################################################
481 # Patches for old functions: these functions should be considered obsolete
482 ##############################################################################
484 def _makeLoader(prefix, sortUsing, suiteClass=None):
485 loader = TestLoader()
486 loader.sortTestMethodsUsing = sortUsing
487 loader.testMethodPrefix = prefix
488 if suiteClass: loader.suiteClass = suiteClass
489 return loader
491 def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
492 return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
494 def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
495 return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
497 def findTestCases(module, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
498 return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
501 ##############################################################################
502 # Text UI
503 ##############################################################################
505 class _WritelnDecorator:
506 """Used to decorate file-like objects with a handy 'writeln' method"""
507 def __init__(self,stream):
508 self.stream = stream
510 def __getattr__(self, attr):
511 return getattr(self.stream,attr)
513 def writeln(self, *args):
514 if args: apply(self.write, args)
515 self.write('\n') # text-mode streams translate to \r\n if needed
518 class _TextTestResult(TestResult):
519 """A test result class that can print formatted text results to a stream.
521 Used by TextTestRunner.
522 """
523 separator1 = '=' * 70
524 separator2 = '-' * 70
526 def __init__(self, stream, descriptions, verbosity):
527 TestResult.__init__(self)
528 self.stream = stream
529 self.showAll = verbosity > 1
530 self.dots = verbosity == 1
531 self.descriptions = descriptions
533 def getDescription(self, test):
534 if self.descriptions:
535 return test.shortDescription() or str(test)
536 else:
537 return str(test)
539 def startTest(self, test):
540 TestResult.startTest(self, test)
541 if self.showAll:
542 self.stream.write(self.getDescription(test))
543 self.stream.write(" ... ")
545 def addSuccess(self, test):
546 TestResult.addSuccess(self, test)
547 if self.showAll:
548 self.stream.writeln("ok")
549 elif self.dots:
550 self.stream.write('.')
552 def addError(self, test, err):
553 TestResult.addError(self, test, err)
554 if self.showAll:
555 self.stream.writeln("ERROR")
556 elif self.dots:
557 self.stream.write('E')
558 if err[0] is KeyboardInterrupt:
559 self.shouldStop = 1
561 def addFailure(self, test, err):
562 TestResult.addFailure(self, test, err)
563 if self.showAll:
564 self.stream.writeln("FAIL")
565 elif self.dots:
566 self.stream.write('F')
568 def printErrors(self):
569 if self.dots or self.showAll:
570 self.stream.writeln()
571 self.printErrorList('ERROR', self.errors)
572 self.printErrorList('FAIL', self.failures)
574 def printErrorList(self, flavour, errors):
575 for test, err in errors:
576 self.stream.writeln(self.separator1)
577 self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
578 self.stream.writeln(self.separator2)
579 for line in apply(traceback.format_exception, err):
580 for l in string.split(line,"\n")[:-1]:
581 self.stream.writeln("%s" % l)
584 class TextTestRunner:
585 """A test runner class that displays results in textual form.
587 It prints out the names of tests as they are run, errors as they
588 occur, and a summary of the results at the end of the test run.
589 """
590 def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1):
591 self.stream = _WritelnDecorator(stream)
592 self.descriptions = descriptions
593 self.verbosity = verbosity
595 def _makeResult(self):
596 return _TextTestResult(self.stream, self.descriptions, self.verbosity)
598 def run(self, test):
599 "Run the given test case or test suite."
600 result = self._makeResult()
601 startTime = time.time()
602 test(result)
603 stopTime = time.time()
604 timeTaken = float(stopTime - startTime)
605 result.printErrors()
606 self.stream.writeln(result.separator2)
607 run = result.testsRun
608 self.stream.writeln("Ran %d test%s in %.3fs" %
609 (run, run == 1 and "" or "s", timeTaken))
610 self.stream.writeln()
611 if not result.wasSuccessful():
612 self.stream.write("FAILED (")
613 failed, errored = map(len, (result.failures, result.errors))
614 if failed:
615 self.stream.write("failures=%d" % failed)
616 if errored:
617 if failed: self.stream.write(", ")
618 self.stream.write("errors=%d" % errored)
619 self.stream.writeln(")")
620 else:
621 self.stream.writeln("OK")
622 return result
626 ##############################################################################
627 # Facilities for running tests from the command line
628 ##############################################################################
630 class TestProgram:
631 """A command-line program that runs a set of tests; this is primarily
632 for making test modules conveniently executable.
633 """
634 USAGE = """\
635 Usage: %(progName)s [options] [test] [...]
637 Options:
638 -h, --help Show this message
639 -v, --verbose Verbose output
640 -q, --quiet Minimal output
642 Examples:
643 %(progName)s - run default set of tests
644 %(progName)s MyTestSuite - run suite 'MyTestSuite'
645 %(progName)s MyTestCase.testSomething - run MyTestCase.testSomething
646 %(progName)s MyTestCase - run all 'test*' test methods
647 in MyTestCase
648 """
649 def __init__(self, module='__main__', defaultTest=None,
650 argv=None, testRunner=None, testLoader=defaultTestLoader):
651 if type(module) == type(''):
652 self.module = __import__(module)
653 for part in string.split(module,'.')[1:]:
654 self.module = getattr(self.module, part)
655 else:
656 self.module = module
657 if argv is None:
658 argv = sys.argv
659 self.verbosity = 1
660 self.defaultTest = defaultTest
661 self.testRunner = testRunner
662 self.testLoader = testLoader
663 self.progName = os.path.basename(argv[0])
664 self.parseArgs(argv)
665 self.runTests()
667 def usageExit(self, msg=None):
668 if msg: print msg
669 print self.USAGE % self.__dict__
670 sys.exit(2)
672 def parseArgs(self, argv):
673 import getopt
674 try:
675 options, args = getopt.getopt(argv[1:], 'hHvq',
676 ['help','verbose','quiet'])
677 for opt, value in options:
678 if opt in ('-h','-H','--help'):
679 self.usageExit()
680 if opt in ('-q','--quiet'):
681 self.verbosity = 0
682 if opt in ('-v','--verbose'):
683 self.verbosity = 2
684 if len(args) == 0 and self.defaultTest is None:
685 self.test = self.testLoader.loadTestsFromModule(self.module)
686 return
687 if len(args) > 0:
688 self.testNames = args
689 else:
690 self.testNames = (self.defaultTest,)
691 self.createTests()
692 except getopt.error, msg:
693 self.usageExit(msg)
695 def createTests(self):
696 self.test = self.testLoader.loadTestsFromNames(self.testNames,
697 self.module)
699 def runTests(self):
700 if self.testRunner is None:
701 self.testRunner = TextTestRunner(verbosity=self.verbosity)
702 result = self.testRunner.run(self.test)
703 sys.exit(not result.wasSuccessful())
705 main = TestProgram
708 ##############################################################################
709 # Executing this module from the command line
710 ##############################################################################
712 if __name__ == "__main__":
713 main(module=None)