Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c3bfb01

Browse files
committed
Merge #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.
2 parents b83b287 + 5abd76a commit c3bfb01

6 files changed

Lines changed: 84 additions & 6 deletions

File tree

Doc/library/doctest.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,16 @@ from text files and modules with doctests:
10241024

10251025
This function uses the same search technique as :func:`testmod`.
10261026

1027+
.. note::
1028+
Unlike :func:`testmod` and :class:`DocTestFinder`, this function raises
1029+
a :exc:`ValueError` if *module* contains no docstrings. You can prevent
1030+
this error by passing a :class:`DocTestFinder` instance as the
1031+
*test_finder* argument with its *exclude_empty* keyword argument set
1032+
to ``False``::
1033+
1034+
>>> finder = doctest.DocTestFinder(exclude_empty=False)
1035+
>>> suite = doctest.DocTestSuite(test_finder=finder)
1036+
10271037

10281038
Under the covers, :func:`DocTestSuite` creates a :class:`unittest.TestSuite` out
10291039
of :class:`doctest.DocTestCase` instances, and :class:`DocTestCase` is a

Lib/doctest.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2334,7 +2334,12 @@ def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None,
23342334
elif not tests:
23352335
# Why do we want to do this? Because it reveals a bug that might
23362336
# otherwise be hidden.
2337-
raise ValueError(module, "has no tests")
2337+
# It is probably a bug that this exception is not also raised if the
2338+
# number of doctest examples in tests is zero (i.e. if no doctest
2339+
# examples were found). However, we should probably not be raising
2340+
# an exception at all here, though it is too late to make this change
2341+
# for a maintenance release. See also issue #14649.
2342+
raise ValueError(module, "has no docstrings")
23382343

23392344
tests.sort()
23402345
suite = unittest.TestSuite()
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# This is a sample module used for testing doctest.
2+
#
3+
# This module is for testing how doctest handles a module with no
4+
# docstrings.
5+
6+
7+
class Foo(object):
8+
9+
# A class with no docstring.
10+
11+
def __init__(self):
12+
pass
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""This is a sample module used for testing doctest.
2+
3+
This module is for testing how doctest handles a module with docstrings
4+
but no doctest examples.
5+
6+
"""
7+
8+
9+
class Foo(object):
10+
"""A docstring with no doctest examples.
11+
12+
"""
13+
14+
def __init__(self):
15+
pass

Lib/test/test_doctest.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,6 +1986,31 @@ def test_DocTestSuite():
19861986
>>> suite.run(unittest.TestResult())
19871987
<unittest.result.TestResult run=9 errors=0 failures=4>
19881988
1989+
The module need not contain any doctest examples:
1990+
1991+
>>> suite = doctest.DocTestSuite('test.sample_doctest_no_doctests')
1992+
>>> suite.run(unittest.TestResult())
1993+
<unittest.result.TestResult run=0 errors=0 failures=0>
1994+
1995+
However, if DocTestSuite finds no docstrings, it raises an error:
1996+
1997+
>>> try:
1998+
... doctest.DocTestSuite('test.sample_doctest_no_docstrings')
1999+
... except ValueError as e:
2000+
... error = e
2001+
2002+
>>> print(error.args[1])
2003+
has no docstrings
2004+
2005+
You can prevent this error by passing a DocTestFinder instance with
2006+
the `exclude_empty` keyword argument set to False:
2007+
2008+
>>> finder = doctest.DocTestFinder(exclude_empty=False)
2009+
>>> suite = doctest.DocTestSuite('test.sample_doctest_no_docstrings',
2010+
... test_finder=finder)
2011+
>>> suite.run(unittest.TestResult())
2012+
<unittest.result.TestResult run=0 errors=0 failures=0>
2013+
19892014
We can use the current module:
19902015
19912016
>>> suite = test.sample_doctest.test_suite()

Lib/test/test_zipimport_support.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
# test_cmd_line_script (covers the zipimport support in runpy)
3030

3131
# Retrieve some helpers from other test cases
32-
from test import test_doctest, sample_doctest
32+
from test import (test_doctest, sample_doctest, sample_doctest_no_doctests,
33+
sample_doctest_no_docstrings)
3334

3435

3536
def _run_object_doctest(obj, module):
@@ -105,16 +106,26 @@ def test_doctest_issue4197(self):
105106
"test_zipped_doctest")
106107
test_src = test_src.replace("test.sample_doctest",
107108
"sample_zipped_doctest")
108-
sample_src = inspect.getsource(sample_doctest)
109-
sample_src = sample_src.replace("test.test_doctest",
110-
"test_zipped_doctest")
109+
# The sample doctest files rewritten to include in the zipped version.
110+
sample_sources = {}
111+
for mod in [sample_doctest, sample_doctest_no_doctests,
112+
sample_doctest_no_docstrings]:
113+
src = inspect.getsource(mod)
114+
src = src.replace("test.test_doctest", "test_zipped_doctest")
115+
# Rewrite the module name so that, for example,
116+
# "test.sample_doctest" becomes "sample_zipped_doctest".
117+
mod_name = mod.__name__.split(".")[-1]
118+
mod_name = mod_name.replace("sample_", "sample_zipped_")
119+
sample_sources[mod_name] = src
120+
111121
with temp_dir() as d:
112122
script_name = make_script(d, 'test_zipped_doctest',
113123
test_src)
114124
zip_name, run_name = make_zip_script(d, 'test_zip',
115125
script_name)
116126
z = zipfile.ZipFile(zip_name, 'a')
117-
z.writestr("sample_zipped_doctest.py", sample_src)
127+
for mod_name, src in sample_sources.items():
128+
z.writestr(mod_name + ".py", src)
118129
z.close()
119130
if verbose:
120131
zip_file = zipfile.ZipFile(zip_name, 'r')

0 commit comments

Comments
 (0)