blob: 1538a5d4b76131b6015795c1793b964d337e151f [file] [log] [blame]
Fred Drake02538202001-03-21 18:09:46 +00001#!/usr/bin/env python
Steve Purcell5ddd1a82001-03-22 08:45:36 +00002'''
Fred Drake02538202001-03-21 18:09:46 +00003Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
4Smalltalk testing framework.
5
Fred Drake02538202001-03-21 18:09:46 +00006This module contains the core framework classes that form the basis of
7specific test cases and suites (TestCase, TestSuite etc.), and also a
8text-based utility class for running the tests and reporting the results
Jeremy Hyltonefef5da2001-10-22 18:14:15 +00009 (TextTestRunner).
Fred Drake02538202001-03-21 18:09:46 +000010
Steve Purcell5ddd1a82001-03-22 08:45:36 +000011Simple usage:
12
13 import unittest
14
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)
Steve Purcell7b065702001-09-06 08:24:40 +000019 def testMultiply(self):
Steve Purcell5ddd1a82001-03-22 08:45:36 +000020 self.assertEquals((0 * 10), 0)
21 self.assertEquals((5 * 8), 40)
22
23 if __name__ == '__main__':
24 unittest.main()
25
26Further information is available in the bundled documentation, and from
27
28 http://pyunit.sourceforge.net/
29
Fred Drake02538202001-03-21 18:09:46 +000030Copyright (c) 1999, 2000, 2001 Steve Purcell
31This module is free software, and you may redistribute it and/or modify
32it under the same terms as Python itself, so long as this copyright message
33and disclaimer are retained in their original form.
34
35IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
36SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
37THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
38DAMAGE.
39
40THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
41LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
42PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
43AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
44SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
Steve Purcell5ddd1a82001-03-22 08:45:36 +000045'''
Fred Drake02538202001-03-21 18:09:46 +000046
Steve Purcell5ddd1a82001-03-22 08:45:36 +000047__author__ = "Steve Purcell"
48__email__ = "stephen_purcell at yahoo dot com"
Fred Drake02538202001-03-21 18:09:46 +000049__version__ = "$Revision$"[11:-2]
50
51import time
52import sys
53import traceback
54import string
55import os
Steve Purcell5ddd1a82001-03-22 08:45:36 +000056import types
Fred Drake02538202001-03-21 18:09:46 +000057
58##############################################################################
59# Test framework core
60##############################################################################
61
62class TestResult:
63 """Holder for test result information.
64
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.
67
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
Steve Purcell7b065702001-09-06 08:24:40 +000070 contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
Fred Drake656f9ec2001-09-06 19:13:14 +000071 formatted traceback of the error that occurred.
Fred Drake02538202001-03-21 18:09:46 +000072 """
73 def __init__(self):
74 self.failures = []
75 self.errors = []
76 self.testsRun = 0
77 self.shouldStop = 0
78
79 def startTest(self, test):
80 "Called when the given test is about to be run"
81 self.testsRun = self.testsRun + 1
82
83 def stopTest(self, test):
84 "Called when the given test has been run"
85 pass
86
87 def addError(self, test, err):
Steve Purcell7b065702001-09-06 08:24:40 +000088 """Called when an error has occurred. 'err' is a tuple of values as
89 returned by sys.exc_info().
90 """
91 self.errors.append((test, self._exc_info_to_string(err)))
Fred Drake02538202001-03-21 18:09:46 +000092
93 def addFailure(self, test, err):
Steve Purcell7b065702001-09-06 08:24:40 +000094 """Called when an error has occurred. 'err' is a tuple of values as
95 returned by sys.exc_info()."""
96 self.failures.append((test, self._exc_info_to_string(err)))
Fred Drake02538202001-03-21 18:09:46 +000097
Steve Purcell5ddd1a82001-03-22 08:45:36 +000098 def addSuccess(self, test):
99 "Called when a test has completed successfully"
100 pass
101
Fred Drake02538202001-03-21 18:09:46 +0000102 def wasSuccessful(self):
103 "Tells whether or not this result was a success"
104 return len(self.failures) == len(self.errors) == 0
105
106 def stop(self):
107 "Indicates that the tests should be aborted"
108 self.shouldStop = 1
Tim Petersa19a1682001-03-29 04:36:09 +0000109
Steve Purcell7b065702001-09-06 08:24:40 +0000110 def _exc_info_to_string(self, err):
111 """Converts a sys.exc_info()-style tuple of values into a string."""
112 return string.join(apply(traceback.format_exception, err), '')
113
Fred Drake02538202001-03-21 18:09:46 +0000114 def __repr__(self):
115 return "<%s run=%i errors=%i failures=%i>" % \
116 (self.__class__, self.testsRun, len(self.errors),
117 len(self.failures))
118
119
120class TestCase:
121 """A class whose instances are single test cases.
122
Fred Drake02538202001-03-21 18:09:46 +0000123 By default, the test code itself should be placed in a method named
124 'runTest'.
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000125
Tim Petersa19a1682001-03-29 04:36:09 +0000126 If the fixture may be used for many test cases, create as
Fred Drake02538202001-03-21 18:09:46 +0000127 many test methods as are needed. When instantiating such a TestCase
128 subclass, specify in the constructor arguments the name of the test method
129 that the instance is to execute.
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000130
Tim Petersa19a1682001-03-29 04:36:09 +0000131 Test authors should subclass TestCase for their own tests. Construction
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000132 and deconstruction of the test's environment ('fixture') can be
133 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
134
135 If it is necessary to override the __init__ method, the base class
136 __init__ method must always be called. It is important that subclasses
137 should not change the signature of their __init__ method, since instances
138 of the classes are instantiated automatically by parts of the framework
139 in order to be run.
Fred Drake02538202001-03-21 18:09:46 +0000140 """
Steve Purcell15d89272001-04-12 09:05:01 +0000141
142 # This attribute determines which exception will be raised when
143 # the instance's assertion methods fail; test methods raising this
144 # exception will be deemed to have 'failed' rather than 'errored'
145
146 failureException = AssertionError
147
Fred Drake02538202001-03-21 18:09:46 +0000148 def __init__(self, methodName='runTest'):
149 """Create an instance of the class that will use the named test
150 method when executed. Raises a ValueError if the instance does
151 not have a method with the specified name.
152 """
153 try:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000154 self.__testMethodName = methodName
155 testMethod = getattr(self, methodName)
156 self.__testMethodDoc = testMethod.__doc__
Fred Drake02538202001-03-21 18:09:46 +0000157 except AttributeError:
158 raise ValueError, "no such test method in %s: %s" % \
159 (self.__class__, methodName)
160
161 def setUp(self):
162 "Hook method for setting up the test fixture before exercising it."
163 pass
164
165 def tearDown(self):
166 "Hook method for deconstructing the test fixture after testing it."
167 pass
168
169 def countTestCases(self):
170 return 1
171
172 def defaultTestResult(self):
173 return TestResult()
174
175 def shortDescription(self):
176 """Returns a one-line description of the test, or None if no
177 description has been provided.
178
179 The default implementation of this method returns the first line of
180 the specified test method's docstring.
181 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000182 doc = self.__testMethodDoc
Fred Drake02538202001-03-21 18:09:46 +0000183 return doc and string.strip(string.split(doc, "\n")[0]) or None
184
185 def id(self):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000186 return "%s.%s" % (self.__class__, self.__testMethodName)
Fred Drake02538202001-03-21 18:09:46 +0000187
188 def __str__(self):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000189 return "%s (%s)" % (self.__testMethodName, self.__class__)
Fred Drake02538202001-03-21 18:09:46 +0000190
191 def __repr__(self):
192 return "<%s testMethod=%s>" % \
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000193 (self.__class__, self.__testMethodName)
Fred Drake02538202001-03-21 18:09:46 +0000194
195 def run(self, result=None):
196 return self(result)
197
198 def __call__(self, result=None):
199 if result is None: result = self.defaultTestResult()
200 result.startTest(self)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000201 testMethod = getattr(self, self.__testMethodName)
Fred Drake02538202001-03-21 18:09:46 +0000202 try:
203 try:
204 self.setUp()
Guido van Rossum202dd1e2001-12-07 03:39:34 +0000205 except KeyboardInterrupt:
206 raise
Fred Drake02538202001-03-21 18:09:46 +0000207 except:
Jeremy Hyltonefef5da2001-10-22 18:14:15 +0000208 result.addError(self, self.__exc_info())
Fred Drake02538202001-03-21 18:09:46 +0000209 return
210
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000211 ok = 0
Fred Drake02538202001-03-21 18:09:46 +0000212 try:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000213 testMethod()
214 ok = 1
Steve Purcell15d89272001-04-12 09:05:01 +0000215 except self.failureException, e:
Jeremy Hyltonefef5da2001-10-22 18:14:15 +0000216 result.addFailure(self, self.__exc_info())
Guido van Rossum202dd1e2001-12-07 03:39:34 +0000217 except KeyboardInterrupt:
218 raise
Fred Drake02538202001-03-21 18:09:46 +0000219 except:
Jeremy Hyltonefef5da2001-10-22 18:14:15 +0000220 result.addError(self, self.__exc_info())
Fred Drake02538202001-03-21 18:09:46 +0000221
222 try:
223 self.tearDown()
Guido van Rossum202dd1e2001-12-07 03:39:34 +0000224 except KeyboardInterrupt:
225 raise
Fred Drake02538202001-03-21 18:09:46 +0000226 except:
Jeremy Hyltonefef5da2001-10-22 18:14:15 +0000227 result.addError(self, self.__exc_info())
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000228 ok = 0
229 if ok: result.addSuccess(self)
Fred Drake02538202001-03-21 18:09:46 +0000230 finally:
231 result.stopTest(self)
232
233 def debug(self):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000234 """Run the test without collecting errors in a TestResult"""
Fred Drake02538202001-03-21 18:09:46 +0000235 self.setUp()
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000236 getattr(self, self.__testMethodName)()
Fred Drake02538202001-03-21 18:09:46 +0000237 self.tearDown()
238
Steve Purcell15d89272001-04-12 09:05:01 +0000239 def __exc_info(self):
240 """Return a version of sys.exc_info() with the traceback frame
241 minimised; usually the top level of the traceback frame is not
242 needed.
Fred Drake02538202001-03-21 18:09:46 +0000243 """
Steve Purcell15d89272001-04-12 09:05:01 +0000244 exctype, excvalue, tb = sys.exc_info()
245 if sys.platform[:4] == 'java': ## tracebacks look different in Jython
246 return (exctype, excvalue, tb)
247 newtb = tb.tb_next
248 if newtb is None:
249 return (exctype, excvalue, tb)
250 return (exctype, excvalue, newtb)
Fred Drake02538202001-03-21 18:09:46 +0000251
Steve Purcell15d89272001-04-12 09:05:01 +0000252 def fail(self, msg=None):
253 """Fail immediately, with the given message."""
254 raise self.failureException, msg
Fred Drake02538202001-03-21 18:09:46 +0000255
256 def failIf(self, expr, msg=None):
257 "Fail the test if the expression is true."
Steve Purcell15d89272001-04-12 09:05:01 +0000258 if expr: raise self.failureException, msg
Fred Drake02538202001-03-21 18:09:46 +0000259
Steve Purcell15d89272001-04-12 09:05:01 +0000260 def failUnless(self, expr, msg=None):
261 """Fail the test unless the expression is true."""
262 if not expr: raise self.failureException, msg
263
264 def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
265 """Fail unless an exception of class excClass is thrown
Fred Drake02538202001-03-21 18:09:46 +0000266 by callableObj when invoked with arguments args and keyword
267 arguments kwargs. If a different type of exception is
268 thrown, it will not be caught, and the test case will be
269 deemed to have suffered an error, exactly as for an
270 unexpected exception.
271 """
272 try:
273 apply(callableObj, args, kwargs)
274 except excClass:
275 return
276 else:
277 if hasattr(excClass,'__name__'): excName = excClass.__name__
278 else: excName = str(excClass)
Steve Purcell15d89272001-04-12 09:05:01 +0000279 raise self.failureException, excName
Fred Drake02538202001-03-21 18:09:46 +0000280
Steve Purcell15d89272001-04-12 09:05:01 +0000281 def failUnlessEqual(self, first, second, msg=None):
282 """Fail if the two objects are unequal as determined by the '!='
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000283 operator.
284 """
Steve Purcell15d89272001-04-12 09:05:01 +0000285 if first != second:
Steve Purcellca9aaf32001-12-17 10:13:17 +0000286 raise self.failureException, \
287 (msg or '%s != %s' % (`first`, `second`))
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000288
Steve Purcell15d89272001-04-12 09:05:01 +0000289 def failIfEqual(self, first, second, msg=None):
290 """Fail if the two objects are equal as determined by the '=='
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000291 operator.
292 """
Steve Purcell15d89272001-04-12 09:05:01 +0000293 if first == second:
Steve Purcellca9aaf32001-12-17 10:13:17 +0000294 raise self.failureException, \
295 (msg or '%s == %s' % (`first`, `second`))
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000296
Steve Purcell15d89272001-04-12 09:05:01 +0000297 assertEqual = assertEquals = failUnlessEqual
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000298
Steve Purcell15d89272001-04-12 09:05:01 +0000299 assertNotEqual = assertNotEquals = failIfEqual
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000300
Steve Purcell15d89272001-04-12 09:05:01 +0000301 assertRaises = failUnlessRaises
302
303 assert_ = failUnless
304
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000305
Fred Drake02538202001-03-21 18:09:46 +0000306
307class TestSuite:
308 """A test suite is a composite test consisting of a number of TestCases.
309
310 For use, create an instance of TestSuite, then add test case instances.
311 When all tests have been added, the suite can be passed to a test
312 runner, such as TextTestRunner. It will run the individual test cases
313 in the order in which they were added, aggregating the results. When
314 subclassing, do not forget to call the base class constructor.
315 """
316 def __init__(self, tests=()):
317 self._tests = []
318 self.addTests(tests)
319
320 def __repr__(self):
321 return "<%s tests=%s>" % (self.__class__, self._tests)
322
323 __str__ = __repr__
324
325 def countTestCases(self):
326 cases = 0
327 for test in self._tests:
328 cases = cases + test.countTestCases()
329 return cases
330
331 def addTest(self, test):
332 self._tests.append(test)
333
334 def addTests(self, tests):
335 for test in tests:
336 self.addTest(test)
337
338 def run(self, result):
339 return self(result)
340
341 def __call__(self, result):
342 for test in self._tests:
343 if result.shouldStop:
344 break
345 test(result)
346 return result
347
348 def debug(self):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000349 """Run the tests without collecting errors in a TestResult"""
Fred Drake02538202001-03-21 18:09:46 +0000350 for test in self._tests: test.debug()
Fred Drake02538202001-03-21 18:09:46 +0000351
352
353class FunctionTestCase(TestCase):
354 """A test case that wraps a test function.
355
356 This is useful for slipping pre-existing test functions into the
357 PyUnit framework. Optionally, set-up and tidy-up functions can be
358 supplied. As with TestCase, the tidy-up ('tearDown') function will
359 always be called if the set-up ('setUp') function ran successfully.
360 """
361
362 def __init__(self, testFunc, setUp=None, tearDown=None,
363 description=None):
364 TestCase.__init__(self)
365 self.__setUpFunc = setUp
366 self.__tearDownFunc = tearDown
367 self.__testFunc = testFunc
368 self.__description = description
369
370 def setUp(self):
371 if self.__setUpFunc is not None:
372 self.__setUpFunc()
373
374 def tearDown(self):
375 if self.__tearDownFunc is not None:
376 self.__tearDownFunc()
377
378 def runTest(self):
379 self.__testFunc()
380
381 def id(self):
382 return self.__testFunc.__name__
383
384 def __str__(self):
385 return "%s (%s)" % (self.__class__, self.__testFunc.__name__)
386
387 def __repr__(self):
388 return "<%s testFunc=%s>" % (self.__class__, self.__testFunc)
389
390 def shortDescription(self):
391 if self.__description is not None: return self.__description
392 doc = self.__testFunc.__doc__
393 return doc and string.strip(string.split(doc, "\n")[0]) or None
394
395
396
397##############################################################################
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000398# Locating and loading tests
Fred Drake02538202001-03-21 18:09:46 +0000399##############################################################################
400
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000401class TestLoader:
402 """This class is responsible for loading tests according to various
403 criteria and returning them wrapped in a Test
Fred Drake02538202001-03-21 18:09:46 +0000404 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000405 testMethodPrefix = 'test'
406 sortTestMethodsUsing = cmp
407 suiteClass = TestSuite
Fred Drake02538202001-03-21 18:09:46 +0000408
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000409 def loadTestsFromTestCase(self, testCaseClass):
Steve Purcell15d89272001-04-12 09:05:01 +0000410 """Return a suite of all tests cases contained in testCaseClass"""
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000411 return self.suiteClass(map(testCaseClass,
412 self.getTestCaseNames(testCaseClass)))
Fred Drake02538202001-03-21 18:09:46 +0000413
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000414 def loadTestsFromModule(self, module):
Steve Purcell15d89272001-04-12 09:05:01 +0000415 """Return a suite of all tests cases contained in the given module"""
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000416 tests = []
417 for name in dir(module):
418 obj = getattr(module, name)
419 if type(obj) == types.ClassType and issubclass(obj, TestCase):
420 tests.append(self.loadTestsFromTestCase(obj))
421 return self.suiteClass(tests)
Fred Drake02538202001-03-21 18:09:46 +0000422
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000423 def loadTestsFromName(self, name, module=None):
Steve Purcell15d89272001-04-12 09:05:01 +0000424 """Return a suite of all tests cases given a string specifier.
425
426 The name may resolve either to a module, a test case class, a
427 test method within a test case class, or a callable object which
428 returns a TestCase or TestSuite instance.
Tim Peters613b2222001-04-13 05:37:27 +0000429
Steve Purcell15d89272001-04-12 09:05:01 +0000430 The method optionally resolves the names relative to a given module.
431 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000432 parts = string.split(name, '.')
433 if module is None:
434 if not parts:
435 raise ValueError, "incomplete test name: %s" % name
436 else:
Steve Purcell17a781b2001-04-09 15:37:31 +0000437 parts_copy = parts[:]
438 while parts_copy:
439 try:
440 module = __import__(string.join(parts_copy,'.'))
441 break
442 except ImportError:
443 del parts_copy[-1]
444 if not parts_copy: raise
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000445 parts = parts[1:]
446 obj = module
447 for part in parts:
448 obj = getattr(obj, part)
Fred Drake02538202001-03-21 18:09:46 +0000449
Steve Purcelle00dde22001-08-08 07:57:26 +0000450 import unittest
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000451 if type(obj) == types.ModuleType:
452 return self.loadTestsFromModule(obj)
Steve Purcelle00dde22001-08-08 07:57:26 +0000453 elif type(obj) == types.ClassType and issubclass(obj, unittest.TestCase):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000454 return self.loadTestsFromTestCase(obj)
455 elif type(obj) == types.UnboundMethodType:
456 return obj.im_class(obj.__name__)
457 elif callable(obj):
458 test = obj()
Steve Purcelle00dde22001-08-08 07:57:26 +0000459 if not isinstance(test, unittest.TestCase) and \
460 not isinstance(test, unittest.TestSuite):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000461 raise ValueError, \
Steve Purcell4bc80852001-05-10 01:28:40 +0000462 "calling %s returned %s, not a test" % (obj,test)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000463 return test
Fred Drake02538202001-03-21 18:09:46 +0000464 else:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000465 raise ValueError, "don't know how to make test from: %s" % obj
466
467 def loadTestsFromNames(self, names, module=None):
Steve Purcell15d89272001-04-12 09:05:01 +0000468 """Return a suite of all tests cases found using the given sequence
469 of string specifiers. See 'loadTestsFromName()'.
470 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000471 suites = []
472 for name in names:
473 suites.append(self.loadTestsFromName(name, module))
474 return self.suiteClass(suites)
475
476 def getTestCaseNames(self, testCaseClass):
Steve Purcell15d89272001-04-12 09:05:01 +0000477 """Return a sorted sequence of method names found within testCaseClass
478 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000479 testFnNames = filter(lambda n,p=self.testMethodPrefix: n[:len(p)] == p,
480 dir(testCaseClass))
481 for baseclass in testCaseClass.__bases__:
482 for testFnName in self.getTestCaseNames(baseclass):
483 if testFnName not in testFnNames: # handle overridden methods
484 testFnNames.append(testFnName)
485 if self.sortTestMethodsUsing:
486 testFnNames.sort(self.sortTestMethodsUsing)
487 return testFnNames
488
489
490
491defaultTestLoader = TestLoader()
492
493
494##############################################################################
495# Patches for old functions: these functions should be considered obsolete
496##############################################################################
497
498def _makeLoader(prefix, sortUsing, suiteClass=None):
499 loader = TestLoader()
500 loader.sortTestMethodsUsing = sortUsing
501 loader.testMethodPrefix = prefix
502 if suiteClass: loader.suiteClass = suiteClass
503 return loader
504
505def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
506 return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
507
508def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
509 return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
510
511def findTestCases(module, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
512 return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
Fred Drake02538202001-03-21 18:09:46 +0000513
514
515##############################################################################
516# Text UI
517##############################################################################
518
519class _WritelnDecorator:
520 """Used to decorate file-like objects with a handy 'writeln' method"""
521 def __init__(self,stream):
522 self.stream = stream
Fred Drake02538202001-03-21 18:09:46 +0000523
524 def __getattr__(self, attr):
525 return getattr(self.stream,attr)
526
527 def writeln(self, *args):
528 if args: apply(self.write, args)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000529 self.write('\n') # text-mode streams translate to \r\n if needed
Tim Petersa19a1682001-03-29 04:36:09 +0000530
Fred Drake02538202001-03-21 18:09:46 +0000531
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000532class _TextTestResult(TestResult):
Fred Drake02538202001-03-21 18:09:46 +0000533 """A test result class that can print formatted text results to a stream.
534
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000535 Used by TextTestRunner.
Fred Drake02538202001-03-21 18:09:46 +0000536 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000537 separator1 = '=' * 70
538 separator2 = '-' * 70
Fred Drake02538202001-03-21 18:09:46 +0000539
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000540 def __init__(self, stream, descriptions, verbosity):
Fred Drake02538202001-03-21 18:09:46 +0000541 TestResult.__init__(self)
542 self.stream = stream
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000543 self.showAll = verbosity > 1
544 self.dots = verbosity == 1
Fred Drake02538202001-03-21 18:09:46 +0000545 self.descriptions = descriptions
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000546
547 def getDescription(self, test):
548 if self.descriptions:
549 return test.shortDescription() or str(test)
550 else:
551 return str(test)
552
Fred Drake02538202001-03-21 18:09:46 +0000553 def startTest(self, test):
554 TestResult.startTest(self, test)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000555 if self.showAll:
556 self.stream.write(self.getDescription(test))
557 self.stream.write(" ... ")
Fred Drake02538202001-03-21 18:09:46 +0000558
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000559 def addSuccess(self, test):
560 TestResult.addSuccess(self, test)
561 if self.showAll:
Fred Drake02538202001-03-21 18:09:46 +0000562 self.stream.writeln("ok")
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000563 elif self.dots:
564 self.stream.write('.')
Fred Drake02538202001-03-21 18:09:46 +0000565
566 def addError(self, test, err):
567 TestResult.addError(self, test, err)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000568 if self.showAll:
569 self.stream.writeln("ERROR")
570 elif self.dots:
571 self.stream.write('E')
Fred Drake02538202001-03-21 18:09:46 +0000572
573 def addFailure(self, test, err):
574 TestResult.addFailure(self, test, err)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000575 if self.showAll:
576 self.stream.writeln("FAIL")
577 elif self.dots:
578 self.stream.write('F')
Fred Drake02538202001-03-21 18:09:46 +0000579
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000580 def printErrors(self):
581 if self.dots or self.showAll:
Fred Drake02538202001-03-21 18:09:46 +0000582 self.stream.writeln()
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000583 self.printErrorList('ERROR', self.errors)
584 self.printErrorList('FAIL', self.failures)
585
586 def printErrorList(self, flavour, errors):
587 for test, err in errors:
588 self.stream.writeln(self.separator1)
589 self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
590 self.stream.writeln(self.separator2)
Steve Purcell7b065702001-09-06 08:24:40 +0000591 self.stream.writeln("%s" % err)
Fred Drake02538202001-03-21 18:09:46 +0000592
593
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000594class TextTestRunner:
Fred Drake02538202001-03-21 18:09:46 +0000595 """A test runner class that displays results in textual form.
Tim Petersa19a1682001-03-29 04:36:09 +0000596
Fred Drake02538202001-03-21 18:09:46 +0000597 It prints out the names of tests as they are run, errors as they
598 occur, and a summary of the results at the end of the test run.
599 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000600 def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1):
Fred Drake02538202001-03-21 18:09:46 +0000601 self.stream = _WritelnDecorator(stream)
602 self.descriptions = descriptions
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000603 self.verbosity = verbosity
604
605 def _makeResult(self):
606 return _TextTestResult(self.stream, self.descriptions, self.verbosity)
Fred Drake02538202001-03-21 18:09:46 +0000607
608 def run(self, test):
609 "Run the given test case or test suite."
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000610 result = self._makeResult()
Fred Drake02538202001-03-21 18:09:46 +0000611 startTime = time.time()
612 test(result)
613 stopTime = time.time()
614 timeTaken = float(stopTime - startTime)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000615 result.printErrors()
616 self.stream.writeln(result.separator2)
Fred Drake02538202001-03-21 18:09:46 +0000617 run = result.testsRun
618 self.stream.writeln("Ran %d test%s in %.3fs" %
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000619 (run, run == 1 and "" or "s", timeTaken))
Fred Drake02538202001-03-21 18:09:46 +0000620 self.stream.writeln()
621 if not result.wasSuccessful():
622 self.stream.write("FAILED (")
623 failed, errored = map(len, (result.failures, result.errors))
624 if failed:
625 self.stream.write("failures=%d" % failed)
626 if errored:
627 if failed: self.stream.write(", ")
628 self.stream.write("errors=%d" % errored)
629 self.stream.writeln(")")
630 else:
631 self.stream.writeln("OK")
632 return result
Tim Petersa19a1682001-03-29 04:36:09 +0000633
Fred Drake02538202001-03-21 18:09:46 +0000634
Fred Drake02538202001-03-21 18:09:46 +0000635
636##############################################################################
637# Facilities for running tests from the command line
638##############################################################################
639
640class TestProgram:
641 """A command-line program that runs a set of tests; this is primarily
642 for making test modules conveniently executable.
643 """
644 USAGE = """\
Steve Purcell17a781b2001-04-09 15:37:31 +0000645Usage: %(progName)s [options] [test] [...]
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000646
647Options:
648 -h, --help Show this message
649 -v, --verbose Verbose output
650 -q, --quiet Minimal output
Fred Drake02538202001-03-21 18:09:46 +0000651
652Examples:
653 %(progName)s - run default set of tests
654 %(progName)s MyTestSuite - run suite 'MyTestSuite'
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000655 %(progName)s MyTestCase.testSomething - run MyTestCase.testSomething
656 %(progName)s MyTestCase - run all 'test*' test methods
Fred Drake02538202001-03-21 18:09:46 +0000657 in MyTestCase
658"""
659 def __init__(self, module='__main__', defaultTest=None,
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000660 argv=None, testRunner=None, testLoader=defaultTestLoader):
Fred Drake02538202001-03-21 18:09:46 +0000661 if type(module) == type(''):
662 self.module = __import__(module)
663 for part in string.split(module,'.')[1:]:
664 self.module = getattr(self.module, part)
665 else:
666 self.module = module
667 if argv is None:
668 argv = sys.argv
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000669 self.verbosity = 1
Fred Drake02538202001-03-21 18:09:46 +0000670 self.defaultTest = defaultTest
671 self.testRunner = testRunner
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000672 self.testLoader = testLoader
Fred Drake02538202001-03-21 18:09:46 +0000673 self.progName = os.path.basename(argv[0])
674 self.parseArgs(argv)
Fred Drake02538202001-03-21 18:09:46 +0000675 self.runTests()
676
677 def usageExit(self, msg=None):
678 if msg: print msg
679 print self.USAGE % self.__dict__
680 sys.exit(2)
681
682 def parseArgs(self, argv):
683 import getopt
684 try:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000685 options, args = getopt.getopt(argv[1:], 'hHvq',
686 ['help','verbose','quiet'])
Fred Drake02538202001-03-21 18:09:46 +0000687 for opt, value in options:
688 if opt in ('-h','-H','--help'):
689 self.usageExit()
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000690 if opt in ('-q','--quiet'):
691 self.verbosity = 0
692 if opt in ('-v','--verbose'):
693 self.verbosity = 2
Fred Drake02538202001-03-21 18:09:46 +0000694 if len(args) == 0 and self.defaultTest is None:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000695 self.test = self.testLoader.loadTestsFromModule(self.module)
696 return
Fred Drake02538202001-03-21 18:09:46 +0000697 if len(args) > 0:
698 self.testNames = args
699 else:
700 self.testNames = (self.defaultTest,)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000701 self.createTests()
Fred Drake02538202001-03-21 18:09:46 +0000702 except getopt.error, msg:
703 self.usageExit(msg)
704
705 def createTests(self):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000706 self.test = self.testLoader.loadTestsFromNames(self.testNames,
707 self.module)
Fred Drake02538202001-03-21 18:09:46 +0000708
709 def runTests(self):
710 if self.testRunner is None:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000711 self.testRunner = TextTestRunner(verbosity=self.verbosity)
Fred Drake02538202001-03-21 18:09:46 +0000712 result = self.testRunner.run(self.test)
Tim Petersa19a1682001-03-29 04:36:09 +0000713 sys.exit(not result.wasSuccessful())
Fred Drake02538202001-03-21 18:09:46 +0000714
715main = TestProgram
716
717
718##############################################################################
719# Executing this module from the command line
720##############################################################################
721
722if __name__ == "__main__":
723 main(module=None)