blob: 9100a78dbbf98d1bb28c1a2e9e8ad476d9bc3693 [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"
Steve Purcelldc391a62002-08-09 09:46:23 +000049__version__ = "#Revision: 1.46 $"[11:-2]
Fred Drake02538202001-03-21 18:09:46 +000050
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
Steve Purcell824574d2002-08-08 13:38:02 +000062# All classes defined herein are 'new-style' classes, allowing use of 'super()'
63__metaclass__ = type
64
Steve Purcelldc391a62002-08-09 09:46:23 +000065def _strclass(cls):
66 return "%s.%s" % (cls.__module__, cls.__name__)
67
Fred Drake02538202001-03-21 18:09:46 +000068class TestResult:
69 """Holder for test result information.
70
71 Test results are automatically managed by the TestCase and TestSuite
72 classes, and do not need to be explicitly manipulated by writers of tests.
73
74 Each instance holds the total number of tests run, and collections of
75 failures and errors that occurred among those test runs. The collections
Steve Purcell7b065702001-09-06 08:24:40 +000076 contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
Fred Drake656f9ec2001-09-06 19:13:14 +000077 formatted traceback of the error that occurred.
Fred Drake02538202001-03-21 18:09:46 +000078 """
79 def __init__(self):
80 self.failures = []
81 self.errors = []
82 self.testsRun = 0
83 self.shouldStop = 0
84
85 def startTest(self, test):
86 "Called when the given test is about to be run"
87 self.testsRun = self.testsRun + 1
88
89 def stopTest(self, test):
90 "Called when the given test has been run"
91 pass
92
93 def addError(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 """
97 self.errors.append((test, self._exc_info_to_string(err)))
Fred Drake02538202001-03-21 18:09:46 +000098
99 def addFailure(self, test, err):
Steve Purcell7b065702001-09-06 08:24:40 +0000100 """Called when an error has occurred. 'err' is a tuple of values as
101 returned by sys.exc_info()."""
102 self.failures.append((test, self._exc_info_to_string(err)))
Fred Drake02538202001-03-21 18:09:46 +0000103
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000104 def addSuccess(self, test):
105 "Called when a test has completed successfully"
106 pass
107
Fred Drake02538202001-03-21 18:09:46 +0000108 def wasSuccessful(self):
109 "Tells whether or not this result was a success"
110 return len(self.failures) == len(self.errors) == 0
111
112 def stop(self):
113 "Indicates that the tests should be aborted"
114 self.shouldStop = 1
Tim Petersa19a1682001-03-29 04:36:09 +0000115
Steve Purcell7b065702001-09-06 08:24:40 +0000116 def _exc_info_to_string(self, err):
117 """Converts a sys.exc_info()-style tuple of values into a string."""
118 return string.join(apply(traceback.format_exception, err), '')
119
Fred Drake02538202001-03-21 18:09:46 +0000120 def __repr__(self):
121 return "<%s run=%i errors=%i failures=%i>" % \
Steve Purcelldc391a62002-08-09 09:46:23 +0000122 (_strclass(self.__class__), self.testsRun, len(self.errors),
Fred Drake02538202001-03-21 18:09:46 +0000123 len(self.failures))
124
125
126class TestCase:
127 """A class whose instances are single test cases.
128
Fred Drake02538202001-03-21 18:09:46 +0000129 By default, the test code itself should be placed in a method named
130 'runTest'.
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000131
Tim Petersa19a1682001-03-29 04:36:09 +0000132 If the fixture may be used for many test cases, create as
Fred Drake02538202001-03-21 18:09:46 +0000133 many test methods as are needed. When instantiating such a TestCase
134 subclass, specify in the constructor arguments the name of the test method
135 that the instance is to execute.
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000136
Tim Petersa19a1682001-03-29 04:36:09 +0000137 Test authors should subclass TestCase for their own tests. Construction
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000138 and deconstruction of the test's environment ('fixture') can be
139 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
140
141 If it is necessary to override the __init__ method, the base class
142 __init__ method must always be called. It is important that subclasses
143 should not change the signature of their __init__ method, since instances
144 of the classes are instantiated automatically by parts of the framework
145 in order to be run.
Fred Drake02538202001-03-21 18:09:46 +0000146 """
Steve Purcell15d89272001-04-12 09:05:01 +0000147
148 # This attribute determines which exception will be raised when
149 # the instance's assertion methods fail; test methods raising this
150 # exception will be deemed to have 'failed' rather than 'errored'
151
152 failureException = AssertionError
153
Fred Drake02538202001-03-21 18:09:46 +0000154 def __init__(self, methodName='runTest'):
155 """Create an instance of the class that will use the named test
156 method when executed. Raises a ValueError if the instance does
157 not have a method with the specified name.
158 """
159 try:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000160 self.__testMethodName = methodName
161 testMethod = getattr(self, methodName)
162 self.__testMethodDoc = testMethod.__doc__
Fred Drake02538202001-03-21 18:09:46 +0000163 except AttributeError:
164 raise ValueError, "no such test method in %s: %s" % \
165 (self.__class__, methodName)
166
167 def setUp(self):
168 "Hook method for setting up the test fixture before exercising it."
169 pass
170
171 def tearDown(self):
172 "Hook method for deconstructing the test fixture after testing it."
173 pass
174
175 def countTestCases(self):
176 return 1
177
178 def defaultTestResult(self):
179 return TestResult()
180
181 def shortDescription(self):
182 """Returns a one-line description of the test, or None if no
183 description has been provided.
184
185 The default implementation of this method returns the first line of
186 the specified test method's docstring.
187 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000188 doc = self.__testMethodDoc
Fred Drake02538202001-03-21 18:09:46 +0000189 return doc and string.strip(string.split(doc, "\n")[0]) or None
190
191 def id(self):
Steve Purcelldc391a62002-08-09 09:46:23 +0000192 return "%s.%s" % (_strclass(self.__class__), self.__testMethodName)
Fred Drake02538202001-03-21 18:09:46 +0000193
194 def __str__(self):
Jeremy Hylton22dae282002-08-13 20:43:46 +0000195 return "%s (%s)" % (self.__testMethodName, _strclass(self.__class__))
Fred Drake02538202001-03-21 18:09:46 +0000196
197 def __repr__(self):
198 return "<%s testMethod=%s>" % \
Steve Purcelldc391a62002-08-09 09:46:23 +0000199 (_strclass(self.__class__), self.__testMethodName)
Fred Drake02538202001-03-21 18:09:46 +0000200
201 def run(self, result=None):
202 return self(result)
203
204 def __call__(self, result=None):
205 if result is None: result = self.defaultTestResult()
206 result.startTest(self)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000207 testMethod = getattr(self, self.__testMethodName)
Fred Drake02538202001-03-21 18:09:46 +0000208 try:
209 try:
210 self.setUp()
Guido van Rossum202dd1e2001-12-07 03:39:34 +0000211 except KeyboardInterrupt:
212 raise
Fred Drake02538202001-03-21 18:09:46 +0000213 except:
Jeremy Hyltonefef5da2001-10-22 18:14:15 +0000214 result.addError(self, self.__exc_info())
Fred Drake02538202001-03-21 18:09:46 +0000215 return
216
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000217 ok = 0
Fred Drake02538202001-03-21 18:09:46 +0000218 try:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000219 testMethod()
220 ok = 1
Steve Purcell15d89272001-04-12 09:05:01 +0000221 except self.failureException, e:
Jeremy Hyltonefef5da2001-10-22 18:14:15 +0000222 result.addFailure(self, self.__exc_info())
Guido van Rossum202dd1e2001-12-07 03:39:34 +0000223 except KeyboardInterrupt:
224 raise
Fred Drake02538202001-03-21 18:09:46 +0000225 except:
Jeremy Hyltonefef5da2001-10-22 18:14:15 +0000226 result.addError(self, self.__exc_info())
Fred Drake02538202001-03-21 18:09:46 +0000227
228 try:
229 self.tearDown()
Guido van Rossum202dd1e2001-12-07 03:39:34 +0000230 except KeyboardInterrupt:
231 raise
Fred Drake02538202001-03-21 18:09:46 +0000232 except:
Jeremy Hyltonefef5da2001-10-22 18:14:15 +0000233 result.addError(self, self.__exc_info())
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000234 ok = 0
235 if ok: result.addSuccess(self)
Fred Drake02538202001-03-21 18:09:46 +0000236 finally:
237 result.stopTest(self)
238
239 def debug(self):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000240 """Run the test without collecting errors in a TestResult"""
Fred Drake02538202001-03-21 18:09:46 +0000241 self.setUp()
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000242 getattr(self, self.__testMethodName)()
Fred Drake02538202001-03-21 18:09:46 +0000243 self.tearDown()
244
Steve Purcell15d89272001-04-12 09:05:01 +0000245 def __exc_info(self):
246 """Return a version of sys.exc_info() with the traceback frame
247 minimised; usually the top level of the traceback frame is not
248 needed.
Fred Drake02538202001-03-21 18:09:46 +0000249 """
Steve Purcell15d89272001-04-12 09:05:01 +0000250 exctype, excvalue, tb = sys.exc_info()
251 if sys.platform[:4] == 'java': ## tracebacks look different in Jython
252 return (exctype, excvalue, tb)
253 newtb = tb.tb_next
254 if newtb is None:
255 return (exctype, excvalue, tb)
256 return (exctype, excvalue, newtb)
Fred Drake02538202001-03-21 18:09:46 +0000257
Steve Purcell15d89272001-04-12 09:05:01 +0000258 def fail(self, msg=None):
259 """Fail immediately, with the given message."""
260 raise self.failureException, msg
Fred Drake02538202001-03-21 18:09:46 +0000261
262 def failIf(self, expr, msg=None):
263 "Fail the test if the expression is true."
Steve Purcell15d89272001-04-12 09:05:01 +0000264 if expr: raise self.failureException, msg
Fred Drake02538202001-03-21 18:09:46 +0000265
Steve Purcell15d89272001-04-12 09:05:01 +0000266 def failUnless(self, expr, msg=None):
267 """Fail the test unless the expression is true."""
268 if not expr: raise self.failureException, msg
269
270 def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
271 """Fail unless an exception of class excClass is thrown
Fred Drake02538202001-03-21 18:09:46 +0000272 by callableObj when invoked with arguments args and keyword
273 arguments kwargs. If a different type of exception is
274 thrown, it will not be caught, and the test case will be
275 deemed to have suffered an error, exactly as for an
276 unexpected exception.
277 """
278 try:
279 apply(callableObj, args, kwargs)
280 except excClass:
281 return
282 else:
283 if hasattr(excClass,'__name__'): excName = excClass.__name__
284 else: excName = str(excClass)
Steve Purcell15d89272001-04-12 09:05:01 +0000285 raise self.failureException, excName
Fred Drake02538202001-03-21 18:09:46 +0000286
Steve Purcell15d89272001-04-12 09:05:01 +0000287 def failUnlessEqual(self, first, second, msg=None):
288 """Fail if the two objects are unequal as determined by the '!='
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000289 operator.
290 """
Steve Purcell15d89272001-04-12 09:05:01 +0000291 if first != second:
Steve Purcellca9aaf32001-12-17 10:13:17 +0000292 raise self.failureException, \
293 (msg or '%s != %s' % (`first`, `second`))
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000294
Steve Purcell15d89272001-04-12 09:05:01 +0000295 def failIfEqual(self, first, second, msg=None):
296 """Fail if the two objects are equal as determined by the '=='
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000297 operator.
298 """
Steve Purcell15d89272001-04-12 09:05:01 +0000299 if first == second:
Steve Purcellca9aaf32001-12-17 10:13:17 +0000300 raise self.failureException, \
301 (msg or '%s == %s' % (`first`, `second`))
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000302
Steve Purcell15d89272001-04-12 09:05:01 +0000303 assertEqual = assertEquals = failUnlessEqual
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000304
Steve Purcell15d89272001-04-12 09:05:01 +0000305 assertNotEqual = assertNotEquals = failIfEqual
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000306
Steve Purcell15d89272001-04-12 09:05:01 +0000307 assertRaises = failUnlessRaises
308
309 assert_ = failUnless
310
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000311
Fred Drake02538202001-03-21 18:09:46 +0000312
313class TestSuite:
314 """A test suite is a composite test consisting of a number of TestCases.
315
316 For use, create an instance of TestSuite, then add test case instances.
317 When all tests have been added, the suite can be passed to a test
318 runner, such as TextTestRunner. It will run the individual test cases
319 in the order in which they were added, aggregating the results. When
320 subclassing, do not forget to call the base class constructor.
321 """
322 def __init__(self, tests=()):
323 self._tests = []
324 self.addTests(tests)
325
326 def __repr__(self):
Steve Purcelldc391a62002-08-09 09:46:23 +0000327 return "<%s tests=%s>" % (_strclass(self.__class__), self._tests)
Fred Drake02538202001-03-21 18:09:46 +0000328
329 __str__ = __repr__
330
331 def countTestCases(self):
332 cases = 0
333 for test in self._tests:
334 cases = cases + test.countTestCases()
335 return cases
336
337 def addTest(self, test):
338 self._tests.append(test)
339
340 def addTests(self, tests):
341 for test in tests:
342 self.addTest(test)
343
344 def run(self, result):
345 return self(result)
346
347 def __call__(self, result):
348 for test in self._tests:
349 if result.shouldStop:
350 break
351 test(result)
352 return result
353
354 def debug(self):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000355 """Run the tests without collecting errors in a TestResult"""
Fred Drake02538202001-03-21 18:09:46 +0000356 for test in self._tests: test.debug()
Fred Drake02538202001-03-21 18:09:46 +0000357
358
359class FunctionTestCase(TestCase):
360 """A test case that wraps a test function.
361
362 This is useful for slipping pre-existing test functions into the
363 PyUnit framework. Optionally, set-up and tidy-up functions can be
364 supplied. As with TestCase, the tidy-up ('tearDown') function will
365 always be called if the set-up ('setUp') function ran successfully.
366 """
367
368 def __init__(self, testFunc, setUp=None, tearDown=None,
369 description=None):
370 TestCase.__init__(self)
371 self.__setUpFunc = setUp
372 self.__tearDownFunc = tearDown
373 self.__testFunc = testFunc
374 self.__description = description
375
376 def setUp(self):
377 if self.__setUpFunc is not None:
378 self.__setUpFunc()
379
380 def tearDown(self):
381 if self.__tearDownFunc is not None:
382 self.__tearDownFunc()
383
384 def runTest(self):
385 self.__testFunc()
386
387 def id(self):
388 return self.__testFunc.__name__
389
390 def __str__(self):
Steve Purcelldc391a62002-08-09 09:46:23 +0000391 return "%s (%s)" % (_strclass(self.__class__), self.__testFunc.__name__)
Fred Drake02538202001-03-21 18:09:46 +0000392
393 def __repr__(self):
Steve Purcelldc391a62002-08-09 09:46:23 +0000394 return "<%s testFunc=%s>" % (_strclass(self.__class__), self.__testFunc)
Fred Drake02538202001-03-21 18:09:46 +0000395
396 def shortDescription(self):
397 if self.__description is not None: return self.__description
398 doc = self.__testFunc.__doc__
399 return doc and string.strip(string.split(doc, "\n")[0]) or None
400
401
402
403##############################################################################
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000404# Locating and loading tests
Fred Drake02538202001-03-21 18:09:46 +0000405##############################################################################
406
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000407class TestLoader:
408 """This class is responsible for loading tests according to various
409 criteria and returning them wrapped in a Test
Fred Drake02538202001-03-21 18:09:46 +0000410 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000411 testMethodPrefix = 'test'
412 sortTestMethodsUsing = cmp
413 suiteClass = TestSuite
Fred Drake02538202001-03-21 18:09:46 +0000414
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000415 def loadTestsFromTestCase(self, testCaseClass):
Steve Purcell15d89272001-04-12 09:05:01 +0000416 """Return a suite of all tests cases contained in testCaseClass"""
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000417 return self.suiteClass(map(testCaseClass,
418 self.getTestCaseNames(testCaseClass)))
Fred Drake02538202001-03-21 18:09:46 +0000419
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000420 def loadTestsFromModule(self, module):
Steve Purcell15d89272001-04-12 09:05:01 +0000421 """Return a suite of all tests cases contained in the given module"""
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000422 tests = []
423 for name in dir(module):
424 obj = getattr(module, name)
Guido van Rossum67911372002-09-30 19:25:56 +0000425 if (isinstance(obj, (type, types.ClassType)) and
426 issubclass(obj, TestCase)):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000427 tests.append(self.loadTestsFromTestCase(obj))
428 return self.suiteClass(tests)
Fred Drake02538202001-03-21 18:09:46 +0000429
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000430 def loadTestsFromName(self, name, module=None):
Steve Purcell15d89272001-04-12 09:05:01 +0000431 """Return a suite of all tests cases given a string specifier.
432
433 The name may resolve either to a module, a test case class, a
434 test method within a test case class, or a callable object which
435 returns a TestCase or TestSuite instance.
Tim Peters613b2222001-04-13 05:37:27 +0000436
Steve Purcell15d89272001-04-12 09:05:01 +0000437 The method optionally resolves the names relative to a given module.
438 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000439 parts = string.split(name, '.')
440 if module is None:
441 if not parts:
442 raise ValueError, "incomplete test name: %s" % name
443 else:
Steve Purcell17a781b2001-04-09 15:37:31 +0000444 parts_copy = parts[:]
445 while parts_copy:
446 try:
447 module = __import__(string.join(parts_copy,'.'))
448 break
449 except ImportError:
450 del parts_copy[-1]
451 if not parts_copy: raise
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000452 parts = parts[1:]
453 obj = module
454 for part in parts:
455 obj = getattr(obj, part)
Fred Drake02538202001-03-21 18:09:46 +0000456
Steve Purcelle00dde22001-08-08 07:57:26 +0000457 import unittest
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000458 if type(obj) == types.ModuleType:
459 return self.loadTestsFromModule(obj)
Guido van Rossum67911372002-09-30 19:25:56 +0000460 elif (isinstance(obj, (type, types.ClassType)) and
461 issubclass(obj, unittest.TestCase)):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000462 return self.loadTestsFromTestCase(obj)
463 elif type(obj) == types.UnboundMethodType:
464 return obj.im_class(obj.__name__)
465 elif callable(obj):
466 test = obj()
Steve Purcelle00dde22001-08-08 07:57:26 +0000467 if not isinstance(test, unittest.TestCase) and \
468 not isinstance(test, unittest.TestSuite):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000469 raise ValueError, \
Steve Purcell4bc80852001-05-10 01:28:40 +0000470 "calling %s returned %s, not a test" % (obj,test)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000471 return test
Fred Drake02538202001-03-21 18:09:46 +0000472 else:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000473 raise ValueError, "don't know how to make test from: %s" % obj
474
475 def loadTestsFromNames(self, names, module=None):
Steve Purcell15d89272001-04-12 09:05:01 +0000476 """Return a suite of all tests cases found using the given sequence
477 of string specifiers. See 'loadTestsFromName()'.
478 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000479 suites = []
480 for name in names:
481 suites.append(self.loadTestsFromName(name, module))
482 return self.suiteClass(suites)
483
484 def getTestCaseNames(self, testCaseClass):
Steve Purcell15d89272001-04-12 09:05:01 +0000485 """Return a sorted sequence of method names found within testCaseClass
486 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000487 testFnNames = filter(lambda n,p=self.testMethodPrefix: n[:len(p)] == p,
488 dir(testCaseClass))
489 for baseclass in testCaseClass.__bases__:
490 for testFnName in self.getTestCaseNames(baseclass):
491 if testFnName not in testFnNames: # handle overridden methods
492 testFnNames.append(testFnName)
493 if self.sortTestMethodsUsing:
494 testFnNames.sort(self.sortTestMethodsUsing)
495 return testFnNames
496
497
498
499defaultTestLoader = TestLoader()
500
501
502##############################################################################
503# Patches for old functions: these functions should be considered obsolete
504##############################################################################
505
506def _makeLoader(prefix, sortUsing, suiteClass=None):
507 loader = TestLoader()
508 loader.sortTestMethodsUsing = sortUsing
509 loader.testMethodPrefix = prefix
510 if suiteClass: loader.suiteClass = suiteClass
511 return loader
512
513def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
514 return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
515
516def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
517 return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
518
519def findTestCases(module, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
520 return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
Fred Drake02538202001-03-21 18:09:46 +0000521
522
523##############################################################################
524# Text UI
525##############################################################################
526
527class _WritelnDecorator:
528 """Used to decorate file-like objects with a handy 'writeln' method"""
529 def __init__(self,stream):
530 self.stream = stream
Fred Drake02538202001-03-21 18:09:46 +0000531
532 def __getattr__(self, attr):
533 return getattr(self.stream,attr)
534
535 def writeln(self, *args):
536 if args: apply(self.write, args)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000537 self.write('\n') # text-mode streams translate to \r\n if needed
Tim Petersa19a1682001-03-29 04:36:09 +0000538
Fred Drake02538202001-03-21 18:09:46 +0000539
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000540class _TextTestResult(TestResult):
Fred Drake02538202001-03-21 18:09:46 +0000541 """A test result class that can print formatted text results to a stream.
542
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000543 Used by TextTestRunner.
Fred Drake02538202001-03-21 18:09:46 +0000544 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000545 separator1 = '=' * 70
546 separator2 = '-' * 70
Fred Drake02538202001-03-21 18:09:46 +0000547
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000548 def __init__(self, stream, descriptions, verbosity):
Fred Drake02538202001-03-21 18:09:46 +0000549 TestResult.__init__(self)
550 self.stream = stream
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000551 self.showAll = verbosity > 1
552 self.dots = verbosity == 1
Fred Drake02538202001-03-21 18:09:46 +0000553 self.descriptions = descriptions
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000554
555 def getDescription(self, test):
556 if self.descriptions:
557 return test.shortDescription() or str(test)
558 else:
559 return str(test)
560
Fred Drake02538202001-03-21 18:09:46 +0000561 def startTest(self, test):
562 TestResult.startTest(self, test)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000563 if self.showAll:
564 self.stream.write(self.getDescription(test))
565 self.stream.write(" ... ")
Fred Drake02538202001-03-21 18:09:46 +0000566
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000567 def addSuccess(self, test):
568 TestResult.addSuccess(self, test)
569 if self.showAll:
Fred Drake02538202001-03-21 18:09:46 +0000570 self.stream.writeln("ok")
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000571 elif self.dots:
572 self.stream.write('.')
Fred Drake02538202001-03-21 18:09:46 +0000573
574 def addError(self, test, err):
575 TestResult.addError(self, test, err)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000576 if self.showAll:
577 self.stream.writeln("ERROR")
578 elif self.dots:
579 self.stream.write('E')
Fred Drake02538202001-03-21 18:09:46 +0000580
581 def addFailure(self, test, err):
582 TestResult.addFailure(self, test, err)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000583 if self.showAll:
584 self.stream.writeln("FAIL")
585 elif self.dots:
586 self.stream.write('F')
Fred Drake02538202001-03-21 18:09:46 +0000587
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000588 def printErrors(self):
589 if self.dots or self.showAll:
Fred Drake02538202001-03-21 18:09:46 +0000590 self.stream.writeln()
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000591 self.printErrorList('ERROR', self.errors)
592 self.printErrorList('FAIL', self.failures)
593
594 def printErrorList(self, flavour, errors):
595 for test, err in errors:
596 self.stream.writeln(self.separator1)
597 self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
598 self.stream.writeln(self.separator2)
Steve Purcell7b065702001-09-06 08:24:40 +0000599 self.stream.writeln("%s" % err)
Fred Drake02538202001-03-21 18:09:46 +0000600
601
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000602class TextTestRunner:
Fred Drake02538202001-03-21 18:09:46 +0000603 """A test runner class that displays results in textual form.
Tim Petersa19a1682001-03-29 04:36:09 +0000604
Fred Drake02538202001-03-21 18:09:46 +0000605 It prints out the names of tests as they are run, errors as they
606 occur, and a summary of the results at the end of the test run.
607 """
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000608 def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1):
Fred Drake02538202001-03-21 18:09:46 +0000609 self.stream = _WritelnDecorator(stream)
610 self.descriptions = descriptions
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000611 self.verbosity = verbosity
612
613 def _makeResult(self):
614 return _TextTestResult(self.stream, self.descriptions, self.verbosity)
Fred Drake02538202001-03-21 18:09:46 +0000615
616 def run(self, test):
617 "Run the given test case or test suite."
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000618 result = self._makeResult()
Fred Drake02538202001-03-21 18:09:46 +0000619 startTime = time.time()
620 test(result)
621 stopTime = time.time()
622 timeTaken = float(stopTime - startTime)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000623 result.printErrors()
624 self.stream.writeln(result.separator2)
Fred Drake02538202001-03-21 18:09:46 +0000625 run = result.testsRun
626 self.stream.writeln("Ran %d test%s in %.3fs" %
Neal Norwitz76165042002-05-31 14:15:11 +0000627 (run, run != 1 and "s" or "", timeTaken))
Fred Drake02538202001-03-21 18:09:46 +0000628 self.stream.writeln()
629 if not result.wasSuccessful():
630 self.stream.write("FAILED (")
631 failed, errored = map(len, (result.failures, result.errors))
632 if failed:
633 self.stream.write("failures=%d" % failed)
634 if errored:
635 if failed: self.stream.write(", ")
636 self.stream.write("errors=%d" % errored)
637 self.stream.writeln(")")
638 else:
639 self.stream.writeln("OK")
640 return result
Tim Petersa19a1682001-03-29 04:36:09 +0000641
Fred Drake02538202001-03-21 18:09:46 +0000642
Fred Drake02538202001-03-21 18:09:46 +0000643
644##############################################################################
645# Facilities for running tests from the command line
646##############################################################################
647
648class TestProgram:
649 """A command-line program that runs a set of tests; this is primarily
650 for making test modules conveniently executable.
651 """
652 USAGE = """\
Steve Purcell17a781b2001-04-09 15:37:31 +0000653Usage: %(progName)s [options] [test] [...]
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000654
655Options:
656 -h, --help Show this message
657 -v, --verbose Verbose output
658 -q, --quiet Minimal output
Fred Drake02538202001-03-21 18:09:46 +0000659
660Examples:
661 %(progName)s - run default set of tests
662 %(progName)s MyTestSuite - run suite 'MyTestSuite'
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000663 %(progName)s MyTestCase.testSomething - run MyTestCase.testSomething
664 %(progName)s MyTestCase - run all 'test*' test methods
Fred Drake02538202001-03-21 18:09:46 +0000665 in MyTestCase
666"""
667 def __init__(self, module='__main__', defaultTest=None,
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000668 argv=None, testRunner=None, testLoader=defaultTestLoader):
Fred Drake02538202001-03-21 18:09:46 +0000669 if type(module) == type(''):
670 self.module = __import__(module)
671 for part in string.split(module,'.')[1:]:
672 self.module = getattr(self.module, part)
673 else:
674 self.module = module
675 if argv is None:
676 argv = sys.argv
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000677 self.verbosity = 1
Fred Drake02538202001-03-21 18:09:46 +0000678 self.defaultTest = defaultTest
679 self.testRunner = testRunner
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000680 self.testLoader = testLoader
Fred Drake02538202001-03-21 18:09:46 +0000681 self.progName = os.path.basename(argv[0])
682 self.parseArgs(argv)
Fred Drake02538202001-03-21 18:09:46 +0000683 self.runTests()
684
685 def usageExit(self, msg=None):
686 if msg: print msg
687 print self.USAGE % self.__dict__
688 sys.exit(2)
689
690 def parseArgs(self, argv):
691 import getopt
692 try:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000693 options, args = getopt.getopt(argv[1:], 'hHvq',
694 ['help','verbose','quiet'])
Fred Drake02538202001-03-21 18:09:46 +0000695 for opt, value in options:
696 if opt in ('-h','-H','--help'):
697 self.usageExit()
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000698 if opt in ('-q','--quiet'):
699 self.verbosity = 0
700 if opt in ('-v','--verbose'):
701 self.verbosity = 2
Fred Drake02538202001-03-21 18:09:46 +0000702 if len(args) == 0 and self.defaultTest is None:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000703 self.test = self.testLoader.loadTestsFromModule(self.module)
704 return
Fred Drake02538202001-03-21 18:09:46 +0000705 if len(args) > 0:
706 self.testNames = args
707 else:
708 self.testNames = (self.defaultTest,)
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000709 self.createTests()
Fred Drake02538202001-03-21 18:09:46 +0000710 except getopt.error, msg:
711 self.usageExit(msg)
712
713 def createTests(self):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000714 self.test = self.testLoader.loadTestsFromNames(self.testNames,
715 self.module)
Fred Drake02538202001-03-21 18:09:46 +0000716
717 def runTests(self):
718 if self.testRunner is None:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000719 self.testRunner = TextTestRunner(verbosity=self.verbosity)
Fred Drake02538202001-03-21 18:09:46 +0000720 result = self.testRunner.run(self.test)
Tim Petersa19a1682001-03-29 04:36:09 +0000721 sys.exit(not result.wasSuccessful())
Fred Drake02538202001-03-21 18:09:46 +0000722
723main = TestProgram
724
725
726##############################################################################
727# Executing this module from the command line
728##############################################################################
729
730if __name__ == "__main__":
731 main(module=None)