mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00: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
7 changed files with 107 additions and 46 deletions
|
@ -195,7 +195,7 @@ individual tests are defined with methods whose names start with the letters
|
||||||
represent tests.
|
represent tests.
|
||||||
|
|
||||||
The crux of each test is a call to :meth:`~TestCase.assertEqual` to check for an
|
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.
|
:meth:`~TestCase.assertRaises` to verify that an expected exception gets raised.
|
||||||
These methods are used instead of the :keyword:`assert` statement so the test
|
These methods are used instead of the :keyword:`assert` statement so the test
|
||||||
runner can accumulate all test results and produce a report.
|
runner can accumulate all test results and produce a report.
|
||||||
|
@ -677,6 +677,7 @@ Test cases
|
||||||
|
|
||||||
.. deprecated:: 3.1
|
.. deprecated:: 3.1
|
||||||
:meth:`failUnless`.
|
:meth:`failUnless`.
|
||||||
|
:meth:`assert_`; use :meth:`assertTrue`.
|
||||||
|
|
||||||
|
|
||||||
.. method:: assertEqual(first, second, msg=None)
|
.. method:: assertEqual(first, second, msg=None)
|
||||||
|
@ -1067,14 +1068,13 @@ Test cases
|
||||||
Returns a description of the test, or :const:`None` if no description
|
Returns a description of the test, or :const:`None` if no description
|
||||||
has been provided. The default implementation of this method
|
has been provided. The default implementation of this method
|
||||||
returns the first line of the test method's docstring, if available,
|
returns the first line of the test method's docstring, if available,
|
||||||
along with the method name.
|
or :const:`None`.
|
||||||
|
|
||||||
.. 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.
|
|
||||||
|
|
||||||
|
.. 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)
|
.. method:: addTypeEqualityFunc(typeobj, function)
|
||||||
|
|
||||||
|
@ -1517,6 +1517,14 @@ Loading and running tests
|
||||||
The default implementation appends the test to the instance's
|
The default implementation appends the test to the instance's
|
||||||
:attr:`unexpectedSuccesses` attribute.
|
: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
|
.. data:: defaultTestLoader
|
||||||
|
|
||||||
|
@ -1525,7 +1533,7 @@ Loading and running tests
|
||||||
instead of repeatedly creating new instances.
|
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
|
A basic test runner implementation which prints results on standard error. It
|
||||||
has a few configurable parameters, but is essentially very simple. Graphical
|
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
|
It is not intended to be called directly, but can be overridden in
|
||||||
subclasses to provide a custom ``TestResult``.
|
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)
|
.. 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.assertTrue(test_case is test)
|
||||||
self.assertIsInstance(formatted_exc, str)
|
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
|
### Support code for Test_TestCase
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
|
@ -2458,18 +2487,13 @@ class Test_TestCase(TestCase, TestEquality, TestHashing):
|
||||||
self.assertEqual(events, expected)
|
self.assertEqual(events, expected)
|
||||||
|
|
||||||
def testShortDescriptionWithoutDocstring(self):
|
def testShortDescriptionWithoutDocstring(self):
|
||||||
self.assertEqual(
|
self.assertIsNone(self.shortDescription())
|
||||||
self.shortDescription(),
|
|
||||||
'testShortDescriptionWithoutDocstring (' + __name__ +
|
|
||||||
'.Test_TestCase)')
|
|
||||||
|
|
||||||
def testShortDescriptionWithOneLineDocstring(self):
|
def testShortDescriptionWithOneLineDocstring(self):
|
||||||
"""Tests shortDescription() for a method with a docstring."""
|
"""Tests shortDescription() for a method with a docstring."""
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.shortDescription(),
|
self.shortDescription(),
|
||||||
('testShortDescriptionWithOneLineDocstring '
|
'Tests shortDescription() for a method with a docstring.')
|
||||||
'(' + __name__ + '.Test_TestCase)\n'
|
|
||||||
'Tests shortDescription() for a method with a docstring.'))
|
|
||||||
|
|
||||||
def testShortDescriptionWithMultiLineDocstring(self):
|
def testShortDescriptionWithMultiLineDocstring(self):
|
||||||
"""Tests shortDescription() for a method with a longer docstring.
|
"""Tests shortDescription() for a method with a longer docstring.
|
||||||
|
@ -2480,10 +2504,8 @@ class Test_TestCase(TestCase, TestEquality, TestHashing):
|
||||||
"""
|
"""
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.shortDescription(),
|
self.shortDescription(),
|
||||||
('testShortDescriptionWithMultiLineDocstring '
|
|
||||||
'(' + __name__ + '.Test_TestCase)\n'
|
|
||||||
'Tests shortDescription() for a method with a longer '
|
'Tests shortDescription() for a method with a longer '
|
||||||
'docstring.'))
|
'docstring.')
|
||||||
|
|
||||||
def testAddTypeEqualityFunc(self):
|
def testAddTypeEqualityFunc(self):
|
||||||
class SadSnake(object):
|
class SadSnake(object):
|
||||||
|
@ -3472,6 +3494,19 @@ class Test_TextTestRunner(TestCase):
|
||||||
# StringIO objects never compare equal, a cheap test instead.
|
# StringIO objects never compare equal, a cheap test instead.
|
||||||
self.assertEqual(obj.stream.getvalue(), stream.getvalue())
|
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):
|
class TestDiscovery(TestCase):
|
||||||
|
|
||||||
|
|
|
@ -60,4 +60,7 @@ from .suite import TestSuite
|
||||||
from .loader import (TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,
|
from .loader import (TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,
|
||||||
findTestCases)
|
findTestCases)
|
||||||
from .main import TestProgram, main
|
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()
|
return result.TestResult()
|
||||||
|
|
||||||
def shortDescription(self):
|
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 = self._testMethodDoc
|
||||||
doc_first_line = None
|
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):
|
def id(self):
|
||||||
return "%s.%s" % (util.strclass(self.__class__), self._testMethodName)
|
return "%s.%s" % (util.strclass(self.__class__), self._testMethodName)
|
||||||
|
@ -501,7 +498,6 @@ class TestCase(object):
|
||||||
assertNotEquals = assertNotEqual
|
assertNotEquals = assertNotEqual
|
||||||
assertAlmostEquals = assertAlmostEqual
|
assertAlmostEquals = assertAlmostEqual
|
||||||
assertNotAlmostEquals = assertNotAlmostEqual
|
assertNotAlmostEquals = assertNotAlmostEqual
|
||||||
assert_ = assertTrue
|
|
||||||
|
|
||||||
# These fail* assertion method names are pending deprecation and will
|
# These fail* assertion method names are pending deprecation and will
|
||||||
# be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
|
# be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
|
||||||
|
@ -518,6 +514,7 @@ class TestCase(object):
|
||||||
failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
|
failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
|
||||||
failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
|
failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
|
||||||
failUnless = _deprecate(assertTrue)
|
failUnless = _deprecate(assertTrue)
|
||||||
|
assert_ = _deprecate(assertTrue)
|
||||||
failUnlessRaises = _deprecate(assertRaises)
|
failUnlessRaises = _deprecate(assertRaises)
|
||||||
failIf = _deprecate(assertFalse)
|
failIf = _deprecate(assertFalse)
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ class TestResult(object):
|
||||||
|
|
||||||
def startTest(self, test):
|
def startTest(self, test):
|
||||||
"Called when the given test is about to be run"
|
"Called when the given test is about to be run"
|
||||||
self.testsRun = self.testsRun + 1
|
self.testsRun += 1
|
||||||
|
|
||||||
def startTestRun(self):
|
def startTestRun(self):
|
||||||
"""Called once before any tests are executed.
|
"""Called once before any tests are executed.
|
||||||
|
@ -36,8 +36,7 @@ class TestResult(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def stopTest(self, test):
|
def stopTest(self, test):
|
||||||
"Called when the given test has been run"
|
"""Called when the given test has been run"""
|
||||||
pass
|
|
||||||
|
|
||||||
def stopTestRun(self):
|
def stopTestRun(self):
|
||||||
"""Called once after all tests are executed.
|
"""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
|
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.
|
"""A test result class that can print formatted text results to a stream.
|
||||||
|
|
||||||
Used by TextTestRunner.
|
Used by TextTestRunner.
|
||||||
|
@ -31,27 +31,28 @@ class _TextTestResult(result.TestResult):
|
||||||
separator2 = '-' * 70
|
separator2 = '-' * 70
|
||||||
|
|
||||||
def __init__(self, stream, descriptions, verbosity):
|
def __init__(self, stream, descriptions, verbosity):
|
||||||
super(_TextTestResult, self).__init__()
|
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
|
||||||
self.descriptions = descriptions
|
self.descriptions = descriptions
|
||||||
|
|
||||||
def getDescription(self, test):
|
def getDescription(self, test):
|
||||||
if self.descriptions:
|
doc_first_line = test.shortDescription()
|
||||||
return test.shortDescription() or str(test)
|
if self.descriptions and doc_first_line:
|
||||||
|
return '\n'.join((str(test), doc_first_line))
|
||||||
else:
|
else:
|
||||||
return str(test)
|
return str(test)
|
||||||
|
|
||||||
def startTest(self, test):
|
def startTest(self, test):
|
||||||
super(_TextTestResult, self).startTest(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):
|
||||||
super(_TextTestResult, self).addSuccess(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:
|
||||||
|
@ -59,7 +60,7 @@ class _TextTestResult(result.TestResult):
|
||||||
self.stream.flush()
|
self.stream.flush()
|
||||||
|
|
||||||
def addError(self, test, err):
|
def addError(self, test, err):
|
||||||
super(_TextTestResult, self).addError(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:
|
||||||
|
@ -67,7 +68,7 @@ class _TextTestResult(result.TestResult):
|
||||||
self.stream.flush()
|
self.stream.flush()
|
||||||
|
|
||||||
def addFailure(self, test, err):
|
def addFailure(self, test, err):
|
||||||
super(_TextTestResult, self).addFailure(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:
|
||||||
|
@ -75,7 +76,7 @@ class _TextTestResult(result.TestResult):
|
||||||
self.stream.flush()
|
self.stream.flush()
|
||||||
|
|
||||||
def addSkip(self, test, reason):
|
def addSkip(self, test, reason):
|
||||||
super(_TextTestResult, self).addSkip(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:
|
||||||
|
@ -83,7 +84,7 @@ class _TextTestResult(result.TestResult):
|
||||||
self.stream.flush()
|
self.stream.flush()
|
||||||
|
|
||||||
def addExpectedFailure(self, test, err):
|
def addExpectedFailure(self, test, err):
|
||||||
super(_TextTestResult, self).addExpectedFailure(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:
|
||||||
|
@ -91,7 +92,7 @@ class _TextTestResult(result.TestResult):
|
||||||
self.stream.flush()
|
self.stream.flush()
|
||||||
|
|
||||||
def addUnexpectedSuccess(self, test):
|
def addUnexpectedSuccess(self, test):
|
||||||
super(_TextTestResult, self).addUnexpectedSuccess(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:
|
||||||
|
@ -118,13 +119,18 @@ class TextTestRunner(object):
|
||||||
It prints out the names of tests as they are run, errors as they
|
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.
|
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.stream = _WritelnDecorator(stream)
|
||||||
self.descriptions = descriptions
|
self.descriptions = descriptions
|
||||||
self.verbosity = verbosity
|
self.verbosity = verbosity
|
||||||
|
if resultclass is not None:
|
||||||
|
self.resultclass = resultclass
|
||||||
|
|
||||||
def _makeResult(self):
|
def _makeResult(self):
|
||||||
return _TextTestResult(self.stream, self.descriptions, self.verbosity)
|
return self.resultclass(self.stream, self.descriptions, self.verbosity)
|
||||||
|
|
||||||
def run(self, test):
|
def run(self, test):
|
||||||
"Run the given test case or test suite."
|
"Run the given test case or test suite."
|
||||||
|
|
|
@ -447,6 +447,13 @@ Library
|
||||||
unpickled. This fixes crashes under Windows when trying to run
|
unpickled. This fixes crashes under Windows when trying to run
|
||||||
test_multiprocessing in verbose mode.
|
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
|
- Issue #3001: Add a C implementation of recursive locks which is used by
|
||||||
default when instantiating a `threading.RLock` object. This makes
|
default when instantiating a `threading.RLock` object. This makes
|
||||||
recursive locks as fast as regular non-recursive locks (previously,
|
recursive locks as fast as regular non-recursive locks (previously,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue