#14649: clarify DocTestSuite error when there are no docstrings.

Also adds tests to verify the documented behavior (which is probably a bug, as
indicated in the added comments).

Patch by Chris Jerdonek.
This commit is contained in:
R David Murray 2012-09-10 10:17:13 -04:00
parent 7a8634d8d8
commit 8d580539f0
4 changed files with 57 additions and 6 deletions

View File

@ -1060,6 +1060,16 @@ from text files and modules with doctests:
.. versionchanged:: 2.5
The parameter *encoding* was added.
.. note::
Unlike :func:`testmod` and :class:`DocTestFinder`, this function raises
a :exc:`ValueError` if *module* contains no docstrings. You can prevent
this error by passing a :class:`DocTestFinder` instance as the
*test_finder* argument with its *exclude_empty* keyword argument set
to ``False``::
>>> finder = doctest.DocTestFinder(exclude_empty=False)
>>> suite = doctest.DocTestSuite(test_finder=finder)
.. function:: DocTestSuite([module][, globs][, extraglobs][, test_finder][, setUp][, tearDown][, checker])

View File

@ -2381,7 +2381,12 @@ def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None,
elif not tests:
# Why do we want to do this? Because it reveals a bug that might
# otherwise be hidden.
raise ValueError(module, "has no tests")
# It is probably a bug that this exception is not also raised if the
# number of doctest examples in tests is zero (i.e. if no doctest
# examples were found). However, we should probably not be raising
# an exception at all here, though it is too late to make this change
# for a maintenance release. See also issue #14649.
raise ValueError(module, "has no docstrings")
tests.sort()
suite = unittest.TestSuite()

View File

@ -2006,6 +2006,31 @@ def test_DocTestSuite():
>>> suite.run(unittest.TestResult())
<unittest.result.TestResult run=9 errors=0 failures=4>
The module need not contain any doctest examples:
>>> suite = doctest.DocTestSuite('test.sample_doctest_no_doctests')
>>> suite.run(unittest.TestResult())
<unittest.result.TestResult run=0 errors=0 failures=0>
However, if DocTestSuite finds no docstrings, it raises an error:
>>> try:
... doctest.DocTestSuite('test.sample_doctest_no_docstrings')
... except ValueError as e:
... error = e
>>> print(error.args[1])
has no docstrings
You can prevent this error by passing a DocTestFinder instance with
the `exclude_empty` keyword argument set to False:
>>> finder = doctest.DocTestFinder(exclude_empty=False)
>>> suite = doctest.DocTestSuite('test.sample_doctest_no_docstrings',
... test_finder=finder)
>>> suite.run(unittest.TestResult())
<unittest.result.TestResult run=0 errors=0 failures=0>
We can use the current module:
>>> suite = test.sample_doctest.test_suite()

View File

@ -29,7 +29,8 @@ verbose = test.test_support.verbose
# test_cmd_line_script (covers the zipimport support in runpy)
# Retrieve some helpers from other test cases
from test import test_doctest, sample_doctest
from test import (test_doctest, sample_doctest, sample_doctest_no_doctests,
sample_doctest_no_docstrings)
from test.test_importhooks import ImportHooksBaseTestCase
@ -99,16 +100,26 @@ class ZipSupportTests(ImportHooksBaseTestCase):
"test_zipped_doctest")
test_src = test_src.replace("test.sample_doctest",
"sample_zipped_doctest")
sample_src = inspect.getsource(sample_doctest)
sample_src = sample_src.replace("test.test_doctest",
"test_zipped_doctest")
# The sample doctest files rewritten to include in the zipped version.
sample_sources = {}
for mod in [sample_doctest, sample_doctest_no_doctests,
sample_doctest_no_docstrings]:
src = inspect.getsource(mod)
src = src.replace("test.test_doctest", "test_zipped_doctest")
# Rewrite the module name so that, for example,
# "test.sample_doctest" becomes "sample_zipped_doctest".
mod_name = mod.__name__.split(".")[-1]
mod_name = mod_name.replace("sample_", "sample_zipped_")
sample_sources[mod_name] = src
with temp_dir() as d:
script_name = make_script(d, 'test_zipped_doctest',
test_src)
zip_name, run_name = make_zip_script(d, 'test_zip',
script_name)
z = zipfile.ZipFile(zip_name, 'a')
z.writestr("sample_zipped_doctest.py", sample_src)
for mod_name, src in sample_sources.items():
z.writestr(mod_name + ".py", src)
z.close()
if verbose:
zip_file = zipfile.ZipFile(zip_name, 'r')