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 @@ -2334,7 +2334,10 @@ 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") + # This is probably a bug since tests.countTestCases() can be zero, + # but it would be too big of a change to fix in a maintenance release. + # See also issue #14649. + raise ValueError(module, "has no docstrings") tests.sort() suite = unittest.TestSuite() diff --git a/Lib/test/doctest/__init__.py b/Lib/test/doctest/__init__.py new file mode 100644 --- /dev/null +++ b/Lib/test/doctest/__init__.py @@ -0,0 +1,1 @@ +# diff --git a/Lib/test/doctest/sample_no_docstrings.py b/Lib/test/doctest/sample_no_docstrings.py new file mode 100644 --- /dev/null +++ b/Lib/test/doctest/sample_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/doctest/sample_no_doctests.py b/Lib/test/doctest/sample_no_doctests.py new file mode 100644 --- /dev/null +++ b/Lib/test/doctest/sample_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 @@ -1986,6 +1986,31 @@ >>> suite.run(unittest.TestResult()) + The module need not contain any doctest examples: + + >>> suite = doctest.DocTestSuite('test.doctest.sample_no_doctests') + >>> suite.run(unittest.TestResult()) + + + However, if DocTestSuite finds no docstrings, it raises an error: + + >>> try: + ... doctest.DocTestSuite('test.doctest.sample_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.doctest.sample_no_docstrings', + ... test_finder=finder) + >>> suite.run(unittest.TestResult()) + + We can use the current module: >>> suite = test.sample_doctest.test_suite()