Merged revisions 70558,70561-70563,70568-70571 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r70558 | benjamin.peterson | 2009-03-23 17:29:45 -0500 (Mon, 23 Mar 2009) | 4 lines

  comply with the evilJavaNamingScheme for attribute names

  It seems my love of PEP 8 overrode the need for consistentcy
........
  r70561 | benjamin.peterson | 2009-03-23 18:10:14 -0500 (Mon, 23 Mar 2009) | 1 line

  refactor unittest docs
........
  r70562 | benjamin.peterson | 2009-03-23 18:13:36 -0500 (Mon, 23 Mar 2009) | 1 line

  forgot to document that setUp can be skipped (silly me...)
........
  r70563 | benjamin.peterson | 2009-03-23 18:19:03 -0500 (Mon, 23 Mar 2009) | 1 line

  update from CVS
........
  r70568 | benjamin.peterson | 2009-03-23 19:35:20 -0500 (Mon, 23 Mar 2009) | 1 line

  some cleanup and modernization
........
  r70569 | benjamin.peterson | 2009-03-23 19:36:16 -0500 (Mon, 23 Mar 2009) | 1 line

  remove special metadata
........
  r70570 | benjamin.peterson | 2009-03-23 19:37:12 -0500 (Mon, 23 Mar 2009) | 1 line

  update docstring
........
  r70571 | benjamin.peterson | 2009-03-23 19:39:24 -0500 (Mon, 23 Mar 2009) | 1 line

  add new skipping things to __all__
........
This commit is contained in:
Benjamin Peterson 2009-03-24 00:56:30 +00:00
parent 6b232cdc7f
commit 52baa29033
3 changed files with 625 additions and 586 deletions

File diff suppressed because it is too large Load diff

View file

@ -2372,7 +2372,7 @@ class Test_TestSkipping(TestCase):
test.run(result) test.run(result)
self.assertEqual(events, self.assertEqual(events,
['startTest', 'addExpectedFailure', 'stopTest']) ['startTest', 'addExpectedFailure', 'stopTest'])
self.assertEqual(result.expected_failures[0][0], test) self.assertEqual(result.expectedFailures[0][0], test)
self.assertTrue(result.wasSuccessful()) self.assertTrue(result.wasSuccessful())
def test_unexpected_success(self): def test_unexpected_success(self):
@ -2387,7 +2387,7 @@ class Test_TestSkipping(TestCase):
self.assertEqual(events, self.assertEqual(events,
['startTest', 'addUnexpectedSuccess', 'stopTest']) ['startTest', 'addUnexpectedSuccess', 'stopTest'])
self.assertFalse(result.failures) self.assertFalse(result.failures)
self.assertEqual(result.unexpected_successes, [test]) self.assertEqual(result.unexpectedSuccesses, [test])
self.assertTrue(result.wasSuccessful()) self.assertTrue(result.wasSuccessful())

View file

@ -25,9 +25,10 @@ Simple usage:
Further information is available in the bundled documentation, and from Further information is available in the bundled documentation, and from
http://docs.python.org/lib/module-unittest.html http://docs.python.org/library/unittest.html
Copyright (c) 1999-2003 Steve Purcell Copyright (c) 1999-2003 Steve Purcell
Copyright (c) 2003-2009 Python Software Foundation
This module is free software, and you may redistribute it and/or modify This module is free software, and you may redistribute it and/or modify
it under the same terms as Python itself, so long as this copyright message it under the same terms as Python itself, so long as this copyright message
and disclaimer are retained in their original form. and disclaimer are retained in their original form.
@ -44,10 +45,6 @@ AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
''' '''
__author__ = "Steve Purcell"
__email__ = "stephen_purcell at yahoo dot com"
__version__ = "#Revision: 1.63 $"[11:-2]
import time import time
import sys import sys
import traceback import traceback
@ -58,8 +55,10 @@ import functools
############################################################################## ##############################################################################
# Exported classes and functions # Exported classes and functions
############################################################################## ##############################################################################
__all__ = ['TestResult', 'TestCase', 'TestSuite', 'TextTestRunner', __all__ = ['TestResult', 'TestCase', 'TestSuite', 'ClassTestSuite',
'TestLoader', 'FunctionTestCase', 'main', 'defaultTestLoader'] 'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
'defaultTestLoader', 'SkipException', 'skip', 'skipIf', 'skipUnless',
'expectedFailure']
# Expose obsolete functions for backwards compatibility # Expose obsolete functions for backwards compatibility
__all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases']) __all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
@ -163,8 +162,8 @@ class TestResult(object):
self.errors = [] self.errors = []
self.testsRun = 0 self.testsRun = 0
self.skipped = [] self.skipped = []
self.expected_failures = [] self.expectedFailures = []
self.unexpected_successes = [] self.unexpectedSuccesses = []
self.shouldStop = False self.shouldStop = False
def startTest(self, test): def startTest(self, test):
@ -196,12 +195,12 @@ class TestResult(object):
def addExpectedFailure(self, test, err): def addExpectedFailure(self, test, err):
"""Called when an expected failure/error occured.""" """Called when an expected failure/error occured."""
self.expected_failures.append( self.expectedFailures.append(
(test, self._exc_info_to_string(err, test))) (test, self._exc_info_to_string(err, test)))
def addUnexpectedSuccess(self, test): def addUnexpectedSuccess(self, test):
"""Called when a test was expected to fail, but succeed.""" """Called when a test was expected to fail, but succeed."""
self.unexpected_successes.append(test) self.unexpectedSuccesses.append(test)
def wasSuccessful(self): def wasSuccessful(self):
"Tells whether or not this result was a success" "Tells whether or not this result was a success"
@ -239,7 +238,10 @@ class TestResult(object):
(_strclass(self.__class__), self.testsRun, len(self.errors), (_strclass(self.__class__), self.testsRun, len(self.errors),
len(self.failures)) len(self.failures))
class AssertRaisesContext(object): class AssertRaisesContext(object):
def __init__(self, expected, test_case, callable_obj=None): def __init__(self, expected, test_case, callable_obj=None):
self.expected = expected self.expected = expected
self.failureException = test_case.failureException self.failureException = test_case.failureException
@ -250,8 +252,10 @@ class AssertRaisesContext(object):
self.obj_name = str(callable_obj) self.obj_name = str(callable_obj)
else: else:
self.obj_name = None self.obj_name = None
def __enter__(self): def __enter__(self):
pass pass
def __exit__(self, exc_type, exc_value, traceback): def __exit__(self, exc_type, exc_value, traceback):
if exc_type is None: if exc_type is None:
try: try:
@ -269,6 +273,7 @@ class AssertRaisesContext(object):
# Let unexpected exceptions skip through # Let unexpected exceptions skip through
return False return False
class TestCase(object): class TestCase(object):
"""A class whose instances are single test cases. """A class whose instances are single test cases.
@ -302,13 +307,13 @@ class TestCase(object):
method when executed. Raises a ValueError if the instance does method when executed. Raises a ValueError if the instance does
not have a method with the specified name. not have a method with the specified name.
""" """
try:
self._testMethodName = methodName self._testMethodName = methodName
try:
testMethod = getattr(self, methodName) testMethod = getattr(self, methodName)
self._testMethodDoc = testMethod.__doc__
except AttributeError: except AttributeError:
raise ValueError("no such test method in %s: %s" % \ raise ValueError("no such test method in %s: %s" % \
(self.__class__, methodName)) (self.__class__, methodName))
self._testMethodDoc = testMethod.__doc__
def setUp(self): def setUp(self):
"Hook method for setting up the test fixture before exercising it." "Hook method for setting up the test fixture before exercising it."
@ -339,7 +344,7 @@ class TestCase(object):
def __eq__(self, other): def __eq__(self, other):
if type(self) is not type(other): if type(self) is not type(other):
return False return NotImplemented
return self._testMethodName == other._testMethodName return self._testMethodName == other._testMethodName
@ -357,7 +362,8 @@ class TestCase(object):
(_strclass(self.__class__), self._testMethodName) (_strclass(self.__class__), self._testMethodName)
def run(self, result=None): def run(self, result=None):
if result is None: result = self.defaultTestResult() if result is None:
result = self.defaultTestResult()
result.startTest(self) result.startTest(self)
testMethod = getattr(self, self._testMethodName) testMethod = getattr(self, self._testMethodName)
try: try:
@ -422,11 +428,13 @@ class TestCase(object):
def failIf(self, expr, msg=None): def failIf(self, expr, msg=None):
"Fail the test if the expression is true." "Fail the test if the expression is true."
if expr: raise self.failureException(msg) if expr:
raise self.failureException(msg)
def failUnless(self, expr, msg=None): def failUnless(self, expr, msg=None):
"""Fail the test unless the expression is true.""" """Fail the test unless the expression is true."""
if not expr: raise self.failureException(msg) if not expr:
raise self.failureException(msg)
def failUnlessRaises(self, excClass, callableObj=None, *args, **kwargs): def failUnlessRaises(self, excClass, callableObj=None, *args, **kwargs):
"""Fail unless an exception of class excClass is thrown """Fail unless an exception of class excClass is thrown
@ -520,8 +528,6 @@ class TestSuite(object):
def __repr__(self): def __repr__(self):
return "<%s tests=%s>" % (_strclass(self.__class__), self._tests) return "<%s tests=%s>" % (_strclass(self.__class__), self._tests)
__str__ = __repr__
def __eq__(self, other): def __eq__(self, other):
if not isinstance(other, self.__class__): if not isinstance(other, self.__class__):
return NotImplemented return NotImplemented
@ -566,7 +572,8 @@ class TestSuite(object):
def debug(self): def debug(self):
"""Run the tests without collecting errors in a TestResult""" """Run the tests without collecting errors in a TestResult"""
for test in self._tests: test.debug() for test in self._tests:
test.debug()
class ClassTestSuite(TestSuite): class ClassTestSuite(TestSuite):
@ -609,9 +616,8 @@ class FunctionTestCase(TestCase):
always be called if the set-up ('setUp') function ran successfully. always be called if the set-up ('setUp') function ran successfully.
""" """
def __init__(self, testFunc, setUp=None, tearDown=None, def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
description=None): super(FunctionTestCase, self).__init__()
TestCase.__init__(self)
self.__setUpFunc = setUp self.__setUpFunc = setUp
self.__tearDownFunc = tearDown self.__tearDownFunc = tearDown
self.__testFunc = testFunc self.__testFunc = testFunc
@ -632,8 +638,8 @@ class FunctionTestCase(TestCase):
return self.__testFunc.__name__ return self.__testFunc.__name__
def __eq__(self, other): def __eq__(self, other):
if type(self) is not type(other): if not isinstance(other, self.__class__):
return False return NotImplemented
return self.__setUpFunc == other.__setUpFunc and \ return self.__setUpFunc == other.__setUpFunc and \
self.__tearDownFunc == other.__tearDownFunc and \ self.__tearDownFunc == other.__tearDownFunc and \
@ -680,8 +686,9 @@ def three_way_cmp(x, y):
return (x > y) - (x < y) return (x > y) - (x < y)
class TestLoader(object): class TestLoader(object):
"""This class is responsible for loading tests according to various """
criteria and returning them wrapped in a TestSuite This class is responsible for loading tests according to various criteria
and returning them wrapped in a TestSuite
""" """
testMethodPrefix = 'test' testMethodPrefix = 'test'
sortTestMethodsUsing = staticmethod(three_way_cmp) sortTestMethodsUsing = staticmethod(three_way_cmp)
@ -691,8 +698,8 @@ class TestLoader(object):
def loadTestsFromTestCase(self, testCaseClass): def loadTestsFromTestCase(self, testCaseClass):
"""Return a suite of all tests cases contained in testCaseClass""" """Return a suite of all tests cases contained in testCaseClass"""
if issubclass(testCaseClass, TestSuite): if issubclass(testCaseClass, TestSuite):
raise TypeError("Test cases should not be derived from TestSuite." raise TypeError("Test cases should not be derived from TestSuite." \
"Maybe you meant to derive from TestCase?") " Maybe you meant to derive from TestCase?")
testCaseNames = self.getTestCaseNames(testCaseClass) testCaseNames = self.getTestCaseNames(testCaseClass)
if not testCaseNames and hasattr(testCaseClass, 'runTest'): if not testCaseNames and hasattr(testCaseClass, 'runTest'):
testCaseNames = ['runTest'] testCaseNames = ['runTest']
@ -727,7 +734,8 @@ class TestLoader(object):
break break
except ImportError: except ImportError:
del parts_copy[-1] del parts_copy[-1]
if not parts_copy: raise if not parts_copy:
raise
parts = parts[1:] parts = parts[1:]
obj = module obj = module
for part in parts: for part in parts:
@ -772,8 +780,8 @@ class TestLoader(object):
""" """
def isTestMethod(attrname, testCaseClass=testCaseClass, def isTestMethod(attrname, testCaseClass=testCaseClass,
prefix=self.testMethodPrefix): prefix=self.testMethodPrefix):
return attrname.startswith(prefix) \ return attrname.startswith(prefix) and \
and hasattr(getattr(testCaseClass, attrname), '__call__') hasattr(getattr(testCaseClass, attrname), '__call__')
testFnNames = list(filter(isTestMethod, dir(testCaseClass))) testFnNames = list(filter(isTestMethod, dir(testCaseClass)))
if self.sortTestMethodsUsing: if self.sortTestMethodsUsing:
testFnNames.sort(key=CmpToKey(self.sortTestMethodsUsing)) testFnNames.sort(key=CmpToKey(self.sortTestMethodsUsing))
@ -835,7 +843,7 @@ class _TextTestResult(TestResult):
separator2 = '-' * 70 separator2 = '-' * 70
def __init__(self, stream, descriptions, verbosity): def __init__(self, stream, descriptions, verbosity):
TestResult.__init__(self) super(_TextTestResult, self).__init__()
self.stream = stream self.stream = stream
self.showAll = verbosity > 1 self.showAll = verbosity > 1
self.dots = verbosity == 1 self.dots = verbosity == 1
@ -848,14 +856,14 @@ class _TextTestResult(TestResult):
return str(test) return str(test)
def startTest(self, test): def startTest(self, test):
TestResult.startTest(self, test) super(_TextTestResult, self).startTest(test)
if self.showAll: if self.showAll:
self.stream.write(self.getDescription(test)) self.stream.write(self.getDescription(test))
self.stream.write(" ... ") self.stream.write(" ... ")
self.stream.flush() self.stream.flush()
def addSuccess(self, test): def addSuccess(self, test):
TestResult.addSuccess(self, test) super(_TextTestResult, self).addSuccess(test)
if self.showAll: if self.showAll:
self.stream.writeln("ok") self.stream.writeln("ok")
elif self.dots: elif self.dots:
@ -863,7 +871,7 @@ class _TextTestResult(TestResult):
self.stream.flush() self.stream.flush()
def addError(self, test, err): def addError(self, test, err):
TestResult.addError(self, test, err) super(_TextTestResult, self).addError(test, err)
if self.showAll: if self.showAll:
self.stream.writeln("ERROR") self.stream.writeln("ERROR")
elif self.dots: elif self.dots:
@ -871,7 +879,7 @@ class _TextTestResult(TestResult):
self.stream.flush() self.stream.flush()
def addFailure(self, test, err): def addFailure(self, test, err):
TestResult.addFailure(self, test, err) super(_TextTestResult, self).addFailure(test, err)
if self.showAll: if self.showAll:
self.stream.writeln("FAIL") self.stream.writeln("FAIL")
elif self.dots: elif self.dots:
@ -879,7 +887,7 @@ class _TextTestResult(TestResult):
self.stream.flush() self.stream.flush()
def addSkip(self, test, reason): def addSkip(self, test, reason):
TestResult.addSkip(self, test, reason) super(_TextTestResult, self).addSkip(test, reason)
if self.showAll: if self.showAll:
self.stream.writeln("skipped {0!r}".format(reason)) self.stream.writeln("skipped {0!r}".format(reason))
elif self.dots: elif self.dots:
@ -887,7 +895,7 @@ class _TextTestResult(TestResult):
self.stream.flush() self.stream.flush()
def addExpectedFailure(self, test, err): def addExpectedFailure(self, test, err):
TestResult.addExpectedFailure(self, test, err) super(_TextTestResult, self).addExpectedFailure(test, err)
if self.showAll: if self.showAll:
self.stream.writeln("expected failure") self.stream.writeln("expected failure")
elif self.dots: elif self.dots:
@ -895,7 +903,7 @@ class _TextTestResult(TestResult):
self.stream.flush() self.stream.flush()
def addUnexpectedSuccess(self, test): def addUnexpectedSuccess(self, test):
TestResult.addUnexpectedSuccess(self, test) super(_TextTestResult, self).addUnexpectedSuccess(test)
if self.showAll: if self.showAll:
self.stream.writeln("unexpected success") self.stream.writeln("unexpected success")
elif self.dots: elif self.dots:
@ -943,10 +951,10 @@ class TextTestRunner(object):
self.stream.writeln("Ran %d test%s in %.3fs" % self.stream.writeln("Ran %d test%s in %.3fs" %
(run, run != 1 and "s" or "", timeTaken)) (run, run != 1 and "s" or "", timeTaken))
self.stream.writeln() self.stream.writeln()
results = map(len, (result.expected_failures, results = map(len, (result.expectedFailures,
result.unexpected_successes, result.unexpectedSuccesses,
result.skipped)) result.skipped))
expected_fails, unexpected_successes, skipped = results expectedFails, unexpectedSuccesses, skipped = results
infos = [] infos = []
if not result.wasSuccessful(): if not result.wasSuccessful():
self.stream.write("FAILED") self.stream.write("FAILED")
@ -956,13 +964,13 @@ class TextTestRunner(object):
if errored: if errored:
infos.append("errors=%d" % errored) infos.append("errors=%d" % errored)
else: else:
self.stream.write("OK") self.stream.writeln("OK")
if skipped: if skipped:
infos.append("skipped=%d" % skipped) infos.append("skipped=%d" % skipped)
if expected_fails: if expectedFails:
infos.append("expected failures=%d" % expected_fails) infos.append("expected failures=%d" % expectedFails)
if unexpected_successes: if unexpectedSuccesses:
infos.append("unexpected successes=%d" % unexpected_successes) infos.append("unexpected successes=%d" % unexpectedSuccesses)
if infos: if infos:
self.stream.writeln(" (%s)" % (", ".join(infos),)) self.stream.writeln(" (%s)" % (", ".join(infos),))
return result return result
@ -1012,7 +1020,8 @@ Examples:
self.runTests() self.runTests()
def usageExit(self, msg=None): def usageExit(self, msg=None):
if msg: print(msg) if msg:
print(msg)
print(self.USAGE % self.__dict__) print(self.USAGE % self.__dict__)
sys.exit(2) sys.exit(2)