Merged revisions 78130 via svnmerge from

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

........
  r78130 | michael.foord | 2010-02-10 14:25:12 +0000 (Wed, 10 Feb 2010) | 1 line

  Issue 7893 and Issue 7588
........
This commit is contained in:
Michael Foord 2010-02-10 15:51:42 +00:00
parent 99f69ee7a1
commit 34c9462d71
7 changed files with 107 additions and 46 deletions

View File

@ -195,7 +195,7 @@ individual tests are defined with methods whose names start with the letters
represent tests.
The crux of each test is a call to :meth:`~TestCase.assertEqual` to check for an
expected result; :meth:`~TestCase.assert_` to verify a condition; or
expected result; :meth:`~TestCase.assertTrue` to verify a condition; or
:meth:`~TestCase.assertRaises` to verify that an expected exception gets raised.
These methods are used instead of the :keyword:`assert` statement so the test
runner can accumulate all test results and produce a report.
@ -677,6 +677,7 @@ Test cases
.. deprecated:: 3.1
:meth:`failUnless`.
:meth:`assert_`; use :meth:`assertTrue`.
.. method:: assertEqual(first, second, msg=None)
@ -1067,14 +1068,13 @@ Test cases
Returns a description of the test, or :const:`None` if no description
has been provided. The default implementation of this method
returns the first line of the test method's docstring, if available,
along with the method name.
.. versionchanged:: 3.1
In earlier versions this only returned the first line of the test
method's docstring, if available or the :const:`None`. That led to
undesirable behavior of not printing the test name when someone was
thoughtful enough to write a docstring.
or :const:`None`.
.. versionchanged:: 3.1,3.2
In 3.1 this was changed to add the test name to the short description
even in the presence of a docstring. This caused compatibility issues
with unittest extensions and adding the test name was moved to the
:class:`TextTestResult`.
.. method:: addTypeEqualityFunc(typeobj, function)
@ -1517,6 +1517,14 @@ Loading and running tests
The default implementation appends the test to the instance's
:attr:`unexpectedSuccesses` attribute.
.. class:: TextTestResult(stream, descriptions, verbosity)
A concrete implementation of :class:`TestResult` used by the
:class:`TextTestRunner`.
.. versionadded:: 3.2
This class was previously named ``_TextTestResult``. The old name still
exists as an alias but is deprecated.
.. data:: defaultTestLoader
@ -1525,7 +1533,7 @@ Loading and running tests
instead of repeatedly creating new instances.
.. class:: TextTestRunner(stream=sys.stderr, descriptions=True, verbosity=1)
.. class:: TextTestRunner(stream=sys.stderr, descriptions=True, verbosity=1, runnerclass=None)
A basic test runner implementation which prints results on standard error. It
has a few configurable parameters, but is essentially very simple. Graphical
@ -1537,6 +1545,12 @@ Loading and running tests
It is not intended to be called directly, but can be overridden in
subclasses to provide a custom ``TestResult``.
``_makeResult()`` instantiates the class or callable passed in the
``TextTestRunner`` constructor as the ``resultclass`` argument. It
defaults to :class::`TextTestResult` if no ``resultclass`` is provided.
The result class is instantiated with the following arguments::
stream, descriptions, verbosity
.. function:: main(module='__main__', defaultTest=None, argv=None, testRunner=None, testLoader=unittest.loader.defaultTestLoader, exit=True, verbosity=1)

View File

@ -2044,6 +2044,35 @@ class Test_TestResult(TestCase):
self.assertTrue(test_case is test)
self.assertIsInstance(formatted_exc, str)
def testGetDescriptionWithoutDocstring(self):
result = unittest.TextTestResult(None, True, None)
self.assertEqual(
result.getDescription(self),
'testGetDescriptionWithoutDocstring (' + __name__ +
'.Test_TestResult)')
def testGetDescriptionWithOneLineDocstring(self):
"""Tests getDescription() for a method with a docstring."""
result = unittest.TextTestResult(None, True, None)
self.assertEqual(
result.getDescription(self),
('testGetDescriptionWithOneLineDocstring '
'(' + __name__ + '.Test_TestResult)\n'
'Tests getDescription() for a method with a docstring.'))
def testGetDescriptionWithMultiLineDocstring(self):
"""Tests getDescription() for a method with a longer docstring.
The second line of the docstring.
"""
result = unittest.TextTestResult(None, True, None)
self.assertEqual(
result.getDescription(self),
('testGetDescriptionWithMultiLineDocstring '
'(' + __name__ + '.Test_TestResult)\n'
'Tests getDescription() for a method with a longer '
'docstring.'))
### Support code for Test_TestCase
################################################################
@ -2458,18 +2487,13 @@ class Test_TestCase(TestCase, TestEquality, TestHashing):
self.assertEqual(events, expected)
def testShortDescriptionWithoutDocstring(self):
self.assertEqual(
self.shortDescription(),
'testShortDescriptionWithoutDocstring (' + __name__ +
'.Test_TestCase)')
self.assertIsNone(self.shortDescription())
def testShortDescriptionWithOneLineDocstring(self):
"""Tests shortDescription() for a method with a docstring."""
self.assertEqual(
self.shortDescription(),
('testShortDescriptionWithOneLineDocstring '
'(' + __name__ + '.Test_TestCase)\n'
'Tests shortDescription() for a method with a docstring.'))
'Tests shortDescription() for a method with a docstring.')
def testShortDescriptionWithMultiLineDocstring(self):
"""Tests shortDescription() for a method with a longer docstring.
@ -2480,10 +2504,8 @@ class Test_TestCase(TestCase, TestEquality, TestHashing):
"""
self.assertEqual(
self.shortDescription(),
('testShortDescriptionWithMultiLineDocstring '
'(' + __name__ + '.Test_TestCase)\n'
'Tests shortDescription() for a method with a longer '
'docstring.'))
'docstring.')
def testAddTypeEqualityFunc(self):
class SadSnake(object):
@ -3472,6 +3494,19 @@ class Test_TextTestRunner(TestCase):
# StringIO objects never compare equal, a cheap test instead.
self.assertEqual(obj.stream.getvalue(), stream.getvalue())
def test_resultclass(self):
def MockResultClass(*args):
return args
STREAM = object()
DESCRIPTIONS = object()
VERBOSITY = object()
runner = unittest.TextTestRunner(STREAM, DESCRIPTIONS, VERBOSITY,
resultclass=MockResultClass)
self.assertEqual(runner.resultclass, MockResultClass)
expectedresult = (runner.stream, DESCRIPTIONS, VERBOSITY)
self.assertEqual(runner._makeResult(), expectedresult)
class TestDiscovery(TestCase):

View File

@ -60,4 +60,7 @@ from .suite import TestSuite
from .loader import (TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,
findTestCases)
from .main import TestProgram, main
from .runner import TextTestRunner
from .runner import TextTestRunner, TextTestResult
# deprecated
_TextTestResult = TextTestResult

View File

@ -229,18 +229,15 @@ class TestCase(object):
return result.TestResult()
def shortDescription(self):
"""Returns both the test method name and first line of its docstring.
"""Returns a one-line description of the test, or None if no
description has been provided.
If no docstring is given, only returns the method name.
The default implementation of this method returns the first line of
the specified test method's docstring.
"""
desc = str(self)
doc_first_line = None
doc = self._testMethodDoc
return doc and doc.split("\n")[0].strip() or None
if self._testMethodDoc:
doc_first_line = self._testMethodDoc.split("\n")[0].strip()
if doc_first_line:
desc = '\n'.join((desc, doc_first_line))
return desc
def id(self):
return "%s.%s" % (util.strclass(self.__class__), self._testMethodName)
@ -501,7 +498,6 @@ class TestCase(object):
assertNotEquals = assertNotEqual
assertAlmostEquals = assertAlmostEqual
assertNotAlmostEquals = assertNotAlmostEqual
assert_ = assertTrue
# These fail* assertion method names are pending deprecation and will
# be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
@ -518,6 +514,7 @@ class TestCase(object):
failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
failUnless = _deprecate(assertTrue)
assert_ = _deprecate(assertTrue)
failUnlessRaises = _deprecate(assertRaises)
failIf = _deprecate(assertFalse)

View File

@ -27,7 +27,7 @@ class TestResult(object):
def startTest(self, test):
"Called when the given test is about to be run"
self.testsRun = self.testsRun + 1
self.testsRun += 1
def startTestRun(self):
"""Called once before any tests are executed.
@ -36,8 +36,7 @@ class TestResult(object):
"""
def stopTest(self, test):
"Called when the given test has been run"
pass
"""Called when the given test has been run"""
def stopTestRun(self):
"""Called once after all tests are executed.

View File

@ -22,7 +22,7 @@ class _WritelnDecorator(object):
self.write('\n') # text-mode streams translate to \r\n if needed
class _TextTestResult(result.TestResult):
class TextTestResult(result.TestResult):
"""A test result class that can print formatted text results to a stream.
Used by TextTestRunner.
@ -31,27 +31,28 @@ class _TextTestResult(result.TestResult):
separator2 = '-' * 70
def __init__(self, stream, descriptions, verbosity):
super(_TextTestResult, self).__init__()
super(TextTestResult, self).__init__()
self.stream = stream
self.showAll = verbosity > 1
self.dots = verbosity == 1
self.descriptions = descriptions
def getDescription(self, test):
if self.descriptions:
return test.shortDescription() or str(test)
doc_first_line = test.shortDescription()
if self.descriptions and doc_first_line:
return '\n'.join((str(test), doc_first_line))
else:
return str(test)
def startTest(self, test):
super(_TextTestResult, self).startTest(test)
super(TextTestResult, self).startTest(test)
if self.showAll:
self.stream.write(self.getDescription(test))
self.stream.write(" ... ")
self.stream.flush()
def addSuccess(self, test):
super(_TextTestResult, self).addSuccess(test)
super(TextTestResult, self).addSuccess(test)
if self.showAll:
self.stream.writeln("ok")
elif self.dots:
@ -59,7 +60,7 @@ class _TextTestResult(result.TestResult):
self.stream.flush()
def addError(self, test, err):
super(_TextTestResult, self).addError(test, err)
super(TextTestResult, self).addError(test, err)
if self.showAll:
self.stream.writeln("ERROR")
elif self.dots:
@ -67,7 +68,7 @@ class _TextTestResult(result.TestResult):
self.stream.flush()
def addFailure(self, test, err):
super(_TextTestResult, self).addFailure(test, err)
super(TextTestResult, self).addFailure(test, err)
if self.showAll:
self.stream.writeln("FAIL")
elif self.dots:
@ -75,7 +76,7 @@ class _TextTestResult(result.TestResult):
self.stream.flush()
def addSkip(self, test, reason):
super(_TextTestResult, self).addSkip(test, reason)
super(TextTestResult, self).addSkip(test, reason)
if self.showAll:
self.stream.writeln("skipped {0!r}".format(reason))
elif self.dots:
@ -83,7 +84,7 @@ class _TextTestResult(result.TestResult):
self.stream.flush()
def addExpectedFailure(self, test, err):
super(_TextTestResult, self).addExpectedFailure(test, err)
super(TextTestResult, self).addExpectedFailure(test, err)
if self.showAll:
self.stream.writeln("expected failure")
elif self.dots:
@ -91,7 +92,7 @@ class _TextTestResult(result.TestResult):
self.stream.flush()
def addUnexpectedSuccess(self, test):
super(_TextTestResult, self).addUnexpectedSuccess(test)
super(TextTestResult, self).addUnexpectedSuccess(test)
if self.showAll:
self.stream.writeln("unexpected success")
elif self.dots:
@ -118,13 +119,18 @@ class TextTestRunner(object):
It prints out the names of tests as they are run, errors as they
occur, and a summary of the results at the end of the test run.
"""
def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1):
resultclass = TextTestResult
def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1,
resultclass=None):
self.stream = _WritelnDecorator(stream)
self.descriptions = descriptions
self.verbosity = verbosity
if resultclass is not None:
self.resultclass = resultclass
def _makeResult(self):
return _TextTestResult(self.stream, self.descriptions, self.verbosity)
return self.resultclass(self.stream, self.descriptions, self.verbosity)
def run(self, test):
"Run the given test case or test suite."

View File

@ -447,6 +447,13 @@ Library
unpickled. This fixes crashes under Windows when trying to run
test_multiprocessing in verbose mode.
- Issue #7893: ``unittest.TextTestResult`` is made public and a ``resultclass``
argument added to the TextTestRunner constructor allowing a different result
class to be used without having to subclass.
- Issue 7588: ``unittest.TextTestResult.getDescription`` now includes the test
name in failure reports even if the test has a docstring.
- Issue #3001: Add a C implementation of recursive locks which is used by
default when instantiating a `threading.RLock` object. This makes
recursive locks as fast as regular non-recursive locks (previously,