mirror of https://github.com/python/cpython.git
Added REPORT_ONLY_FIRST_FAILURE flag, which supresses output after the
first failing example in each test.
This commit is contained in:
parent
cc8a4f6563
commit
a89f88d53f
|
@ -364,6 +364,17 @@ can also be used in doctest directives (see below).
|
||||||
positions.
|
positions.
|
||||||
\end{datadesc}
|
\end{datadesc}
|
||||||
|
|
||||||
|
\begin{datadesc}{REPORT_ONLY_FIRST_FAILURE}
|
||||||
|
When specified, display the first failing example in each doctest,
|
||||||
|
but suppress output for all remaining examples. This will prevent
|
||||||
|
doctest from reporting correct examples that break because of
|
||||||
|
earlier failures; but it might also hide incorrect examples that
|
||||||
|
fail independently of the first failure. When
|
||||||
|
\constant{REPORT_ONLY_FIRST_FAILURE} is specified, the remaining
|
||||||
|
examples are still run, and still count towards the total number of
|
||||||
|
failures reported; only the output is suppressed.
|
||||||
|
\end{datadesc}
|
||||||
|
|
||||||
A "doctest directive" is a trailing Python comment on a line of a doctest
|
A "doctest directive" is a trailing Python comment on a line of a doctest
|
||||||
example:
|
example:
|
||||||
|
|
||||||
|
@ -421,8 +432,8 @@ can be useful.
|
||||||
|
|
||||||
\versionchanged[Constants \constant{DONT_ACCEPT_BLANKLINE},
|
\versionchanged[Constants \constant{DONT_ACCEPT_BLANKLINE},
|
||||||
\constant{NORMALIZE_WHITESPACE}, \constant{ELLIPSIS},
|
\constant{NORMALIZE_WHITESPACE}, \constant{ELLIPSIS},
|
||||||
\constant{REPORT_UDIFF}, \constant{REPORT_CDIFF}, and
|
\constant{REPORT_UDIFF}, \constant{REPORT_CDIFF},
|
||||||
\constant{REPORT_NDIFF}
|
\constant{REPORT_NDIFF}, and \constant{REPORT_ONLY_FIRST_FAILURE}
|
||||||
were added; by default \code{<BLANKLINE>} in expected output
|
were added; by default \code{<BLANKLINE>} in expected output
|
||||||
matches an empty line in actual output; and doctest directives
|
matches an empty line in actual output; and doctest directives
|
||||||
were added]{2.4}
|
were added]{2.4}
|
||||||
|
|
|
@ -260,6 +260,7 @@ def register_optionflag(name):
|
||||||
REPORT_UDIFF = register_optionflag('REPORT_UDIFF')
|
REPORT_UDIFF = register_optionflag('REPORT_UDIFF')
|
||||||
REPORT_CDIFF = register_optionflag('REPORT_CDIFF')
|
REPORT_CDIFF = register_optionflag('REPORT_CDIFF')
|
||||||
REPORT_NDIFF = register_optionflag('REPORT_NDIFF')
|
REPORT_NDIFF = register_optionflag('REPORT_NDIFF')
|
||||||
|
REPORT_ONLY_FIRST_FAILURE = register_optionflag('REPORT_ONLY_FIRST_FAILURE')
|
||||||
|
|
||||||
# Special string markers for use in `want` strings:
|
# Special string markers for use in `want` strings:
|
||||||
BLANKLINE_MARKER = '<BLANKLINE>'
|
BLANKLINE_MARKER = '<BLANKLINE>'
|
||||||
|
@ -1280,7 +1281,6 @@ def report_failure(self, out, test, example, got):
|
||||||
"""
|
"""
|
||||||
Report that the given example failed.
|
Report that the given example failed.
|
||||||
"""
|
"""
|
||||||
# Print an error message.
|
|
||||||
out(self._failure_header(test, example) +
|
out(self._failure_header(test, example) +
|
||||||
self._checker.output_difference(example.want, got,
|
self._checker.output_difference(example.want, got,
|
||||||
self.optionflags))
|
self.optionflags))
|
||||||
|
@ -1331,6 +1331,11 @@ def __run(self, test, compileflags, out):
|
||||||
|
|
||||||
# Process each example.
|
# Process each example.
|
||||||
for example in test.examples:
|
for example in test.examples:
|
||||||
|
# If REPORT_ONLY_FIRST_FAILURE is set, then supress
|
||||||
|
# reporting after the first failure.
|
||||||
|
quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and
|
||||||
|
failures > 0)
|
||||||
|
|
||||||
# Merge in the example's options.
|
# Merge in the example's options.
|
||||||
self.optionflags = original_optionflags
|
self.optionflags = original_optionflags
|
||||||
if example.options:
|
if example.options:
|
||||||
|
@ -1342,6 +1347,7 @@ def __run(self, test, compileflags, out):
|
||||||
|
|
||||||
# Record that we started this example.
|
# Record that we started this example.
|
||||||
tries += 1
|
tries += 1
|
||||||
|
if not quiet:
|
||||||
self.report_start(out, test, example)
|
self.report_start(out, test, example)
|
||||||
|
|
||||||
# Run the example in the given context (globs), and record
|
# Run the example in the given context (globs), and record
|
||||||
|
@ -1365,8 +1371,10 @@ def __run(self, test, compileflags, out):
|
||||||
if exception is None:
|
if exception is None:
|
||||||
if self._checker.check_output(example.want, got,
|
if self._checker.check_output(example.want, got,
|
||||||
self.optionflags):
|
self.optionflags):
|
||||||
|
if not quiet:
|
||||||
self.report_success(out, test, example, got)
|
self.report_success(out, test, example, got)
|
||||||
else:
|
else:
|
||||||
|
if not quiet:
|
||||||
self.report_failure(out, test, example, got)
|
self.report_failure(out, test, example, got)
|
||||||
failures += 1
|
failures += 1
|
||||||
|
|
||||||
|
@ -1379,6 +1387,7 @@ def __run(self, test, compileflags, out):
|
||||||
# If `example.exc_msg` is None, then we weren't
|
# If `example.exc_msg` is None, then we weren't
|
||||||
# expecting an exception.
|
# expecting an exception.
|
||||||
if example.exc_msg is None:
|
if example.exc_msg is None:
|
||||||
|
if not quiet:
|
||||||
self.report_unexpected_exception(out, test, example,
|
self.report_unexpected_exception(out, test, example,
|
||||||
exc_info)
|
exc_info)
|
||||||
failures += 1
|
failures += 1
|
||||||
|
@ -1386,12 +1395,14 @@ def __run(self, test, compileflags, out):
|
||||||
# message (`exc_msg`), then the example succeeds.
|
# message (`exc_msg`), then the example succeeds.
|
||||||
elif (self._checker.check_output(example.exc_msg, exc_msg,
|
elif (self._checker.check_output(example.exc_msg, exc_msg,
|
||||||
self.optionflags)):
|
self.optionflags)):
|
||||||
self.report_success(out, test, example,
|
if not quiet:
|
||||||
got + _exception_traceback(exc_info))
|
got += _exception_traceback(exc_info)
|
||||||
|
self.report_success(out, test, example, got)
|
||||||
# Otherwise, the example fails.
|
# Otherwise, the example fails.
|
||||||
else:
|
else:
|
||||||
self.report_failure(out, test, example,
|
if not quiet:
|
||||||
got + _exception_traceback(exc_info))
|
got += _exception_traceback(exc_info)
|
||||||
|
self.report_failure(out, test, example, got)
|
||||||
failures += 1
|
failures += 1
|
||||||
|
|
||||||
# Restore the option flags (in case they were modified)
|
# Restore the option flags (in case they were modified)
|
||||||
|
@ -1842,6 +1853,7 @@ def testmod(m=None, name=None, globs=None, verbose=None, isprivate=None,
|
||||||
REPORT_UDIFF
|
REPORT_UDIFF
|
||||||
REPORT_CDIFF
|
REPORT_CDIFF
|
||||||
REPORT_NDIFF
|
REPORT_NDIFF
|
||||||
|
REPORT_ONLY_FIRST_FAILURE
|
||||||
|
|
||||||
Optional keyword arg "raise_on_error" raises an exception on the
|
Optional keyword arg "raise_on_error" raises an exception on the
|
||||||
first unexpected exception or failure. This allows failures to be
|
first unexpected exception or failure. This allows failures to be
|
||||||
|
|
|
@ -1042,6 +1042,87 @@ def optionflags(): r"""
|
||||||
? + ++ ^
|
? + ++ ^
|
||||||
<BLANKLINE>
|
<BLANKLINE>
|
||||||
(1, 1)
|
(1, 1)
|
||||||
|
|
||||||
|
The REPORT_ONLY_FIRST_FAILURE supresses result output after the first
|
||||||
|
failing example:
|
||||||
|
|
||||||
|
>>> def f(x):
|
||||||
|
... r'''
|
||||||
|
... >>> print 1 # first success
|
||||||
|
... 1
|
||||||
|
... >>> print 2 # first failure
|
||||||
|
... 200
|
||||||
|
... >>> print 3 # second failure
|
||||||
|
... 300
|
||||||
|
... >>> print 4 # second success
|
||||||
|
... 4
|
||||||
|
... >>> print 5 # third failure
|
||||||
|
... 500
|
||||||
|
... '''
|
||||||
|
>>> test = doctest.DocTestFinder().find(f)[0]
|
||||||
|
>>> flags = doctest.REPORT_ONLY_FIRST_FAILURE
|
||||||
|
>>> doctest.DocTestRunner(verbose=False, optionflags=flags).run(test)
|
||||||
|
**********************************************************************
|
||||||
|
Line 4, in f
|
||||||
|
Failed example:
|
||||||
|
print 2 # first failure
|
||||||
|
Expected:
|
||||||
|
200
|
||||||
|
Got:
|
||||||
|
2
|
||||||
|
(3, 5)
|
||||||
|
|
||||||
|
However, output from `report_start` is not supressed:
|
||||||
|
|
||||||
|
>>> doctest.DocTestRunner(verbose=True, optionflags=flags).run(test)
|
||||||
|
Trying:
|
||||||
|
print 1 # first success
|
||||||
|
Expecting:
|
||||||
|
1
|
||||||
|
ok
|
||||||
|
Trying:
|
||||||
|
print 2 # first failure
|
||||||
|
Expecting:
|
||||||
|
200
|
||||||
|
**********************************************************************
|
||||||
|
Line 4, in f
|
||||||
|
Failed example:
|
||||||
|
print 2 # first failure
|
||||||
|
Expected:
|
||||||
|
200
|
||||||
|
Got:
|
||||||
|
2
|
||||||
|
(3, 5)
|
||||||
|
|
||||||
|
For the purposes of REPORT_ONLY_FIRST_FAILURE, unexpected exceptions
|
||||||
|
count as failures:
|
||||||
|
|
||||||
|
>>> def f(x):
|
||||||
|
... r'''
|
||||||
|
... >>> print 1 # first success
|
||||||
|
... 1
|
||||||
|
... >>> raise ValueError(2) # first failure
|
||||||
|
... 200
|
||||||
|
... >>> print 3 # second failure
|
||||||
|
... 300
|
||||||
|
... >>> print 4 # second success
|
||||||
|
... 4
|
||||||
|
... >>> print 5 # third failure
|
||||||
|
... 500
|
||||||
|
... '''
|
||||||
|
>>> test = doctest.DocTestFinder().find(f)[0]
|
||||||
|
>>> flags = doctest.REPORT_ONLY_FIRST_FAILURE
|
||||||
|
>>> doctest.DocTestRunner(verbose=False, optionflags=flags).run(test)
|
||||||
|
... # doctest: +ELLIPSIS
|
||||||
|
**********************************************************************
|
||||||
|
Line 4, in f
|
||||||
|
Failed example:
|
||||||
|
raise ValueError(2) # first failure
|
||||||
|
Exception raised:
|
||||||
|
...
|
||||||
|
ValueError: 2
|
||||||
|
(3, 5)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def option_directives(): r"""
|
def option_directives(): r"""
|
||||||
|
|
Loading…
Reference in New Issue