mirror of
https://github.com/python/cpython.git
synced 2024-11-29 04:44:13 +08:00
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:
parent
99f69ee7a1
commit
34c9462d71
@ -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)
|
||||
|
||||
|
@ -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):
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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."
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user