[Python-checkins] cpython (3.2): #14649: clarify DocTestSuite error when there are no docstrings.

r.david.murray python-checkins at python.org
Mon Sep 10 16:17:33 CEST 2012


http://hg.python.org/cpython/rev/d012f645b8b2
changeset:   78959:d012f645b8b2
branch:      3.2
parent:      78955:5493299df0a0
user:        R David Murray <rdmurray at bitdance.com>
date:        Mon Sep 10 10:15:58 2012 -0400
summary:
  #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.

files:
  Doc/library/doctest.rst                  |  10 ++++
  Lib/doctest.py                           |   7 ++-
  Lib/test/sample_doctest_no_docstrings.py |  12 +++++
  Lib/test/sample_doctest_no_doctests.py   |  15 +++++++
  Lib/test/test_doctest.py                 |  25 ++++++++++++
  Lib/test/test_zipimport_support.py       |  21 +++++++--
  6 files changed, 84 insertions(+), 6 deletions(-)


diff --git a/Doc/library/doctest.rst b/Doc/library/doctest.rst
--- a/Doc/library/doctest.rst
+++ b/Doc/library/doctest.rst
@@ -1024,6 +1024,16 @@
 
    This function uses the same search technique as :func:`testmod`.
 
+   .. 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)
+
 
 Under the covers, :func:`DocTestSuite` creates a :class:`unittest.TestSuite` out
 of :class:`doctest.DocTestCase` instances, and :class:`DocTestCase` is a
diff --git a/Lib/doctest.py b/Lib/doctest.py
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -2333,7 +2333,12 @@
     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()
diff --git a/Lib/test/sample_doctest_no_docstrings.py b/Lib/test/sample_doctest_no_docstrings.py
new file mode 100644
--- /dev/null
+++ b/Lib/test/sample_doctest_no_docstrings.py
@@ -0,0 +1,12 @@
+# This is a sample module used for testing doctest.
+#
+# This module is for testing how doctest handles a module with no
+# docstrings.
+
+
+class Foo(object):
+
+    # A class with no docstring.
+
+    def __init__(self):
+        pass
diff --git a/Lib/test/sample_doctest_no_doctests.py b/Lib/test/sample_doctest_no_doctests.py
new file mode 100644
--- /dev/null
+++ b/Lib/test/sample_doctest_no_doctests.py
@@ -0,0 +1,15 @@
+"""This is a sample module used for testing doctest.
+
+This module is for testing how doctest handles a module with docstrings
+but no doctest examples.
+
+"""
+
+
+class Foo(object):
+    """A docstring with no doctest examples.
+
+    """
+
+    def __init__(self):
+        pass
diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py
--- a/Lib/test/test_doctest.py
+++ b/Lib/test/test_doctest.py
@@ -1984,6 +1984,31 @@
          >>> 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()
diff --git a/Lib/test/test_zipimport_support.py b/Lib/test/test_zipimport_support.py
--- a/Lib/test/test_zipimport_support.py
+++ b/Lib/test/test_zipimport_support.py
@@ -29,7 +29,8 @@
 #  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)
 
 
 def _run_object_doctest(obj, module):
@@ -105,16 +106,26 @@
                                     "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')

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list