From 4c7e74a13d39141497e77c3f23fcc56c74070700 Mon Sep 17 00:00:00 2001 From: Malcolm Smith Date: Wed, 27 Mar 2024 16:53:27 +0000 Subject: [PATCH 1/3] Make DocTestCase report as skipped if all examples in the doctest are skipped --- Doc/library/doctest.rst | 6 ++- Lib/doctest.py | 7 ++-- Lib/test/test_doctest/sample_doctest_skip.py | 37 +++++++++++++++++++ Lib/test/test_doctest/test_doctest.py | 22 +++++++++++ Lib/test/test_doctest/test_doctest_skip.txt | 4 ++ ...-03-27-16-43-42.gh-issue-117294.wbXNFv.rst | 2 + 6 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 Lib/test/test_doctest/sample_doctest_skip.py create mode 100644 Lib/test/test_doctest/test_doctest_skip.txt create mode 100644 Misc/NEWS.d/next/Library/2024-03-27-16-43-42.gh-issue-117294.wbXNFv.rst diff --git a/Doc/library/doctest.rst b/Doc/library/doctest.rst index 835a3a76806148..d3dcf9c4e5743c 100644 --- a/Doc/library/doctest.rst +++ b/Doc/library/doctest.rst @@ -1021,7 +1021,8 @@ from text files and modules with doctests: and runs the interactive examples in each file. If an example in any file fails, then the synthesized unit test fails, and a :exc:`failureException` exception is raised showing the name of the file containing the test and a - (sometimes approximate) line number. + (sometimes approximate) line number. If all the examples in a file are + skipped, then the synthesized unit test is also marked as skipped. Pass one or more paths (as strings) to text files to be examined. @@ -1087,7 +1088,8 @@ from text files and modules with doctests: and runs each doctest in the module. If any of the doctests fail, then the synthesized unit test fails, and a :exc:`failureException` exception is raised showing the name of the file containing the test and a (sometimes approximate) - line number. + line number. If all the examples in a docstring are skipped, then the + synthesized unit test is also marked as skipped. Optional argument *module* provides the module to be tested. It can be a module object or a (possibly dotted) module name. If not specified, the module calling diff --git a/Lib/doctest.py b/Lib/doctest.py index 6049423b5147a5..cac50f9d23439a 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -2262,12 +2262,13 @@ def runTest(self): try: runner.DIVIDER = "-"*70 - failures, tries = runner.run( - test, out=new.write, clear_globs=False) + results = runner.run(test, out=new.write, clear_globs=False) + if results.skipped == results.attempted: + raise unittest.SkipTest(f"all examples were skipped") finally: sys.stdout = old - if failures: + if results.failed: raise self.failureException(self.format_failure(new.getvalue())) def format_failure(self, err): diff --git a/Lib/test/test_doctest/sample_doctest_skip.py b/Lib/test/test_doctest/sample_doctest_skip.py new file mode 100644 index 00000000000000..b140cb2a4a70a2 --- /dev/null +++ b/Lib/test/test_doctest/sample_doctest_skip.py @@ -0,0 +1,37 @@ +"""This is a sample module used for testing doctest. + +This module includes various scenarios involving skips. +""" + +# This test will pass. +def no_skip(): + """ + >>> 2 + 2 + 4 + """ + +def single_skip(): + """ + >>> 2 + 2 # doctest: +SKIP + 4 + """ + +def double_skip(): + """ + >>> 2 + 2 # doctest: +SKIP + 4 + >>> 3 + 3 # doctest: +SKIP + 6 + """ + +# This test will fail. +def partial_skip(): + """ + >>> 2 + 2 # doctest: +SKIP + 4 + >>> 2 + 2 + 5 + """ + +def no_examples(): + """A docstring with no examples should not be counted as a skip.""" diff --git a/Lib/test/test_doctest/test_doctest.py b/Lib/test/test_doctest/test_doctest.py index 43be200b983227..9ec8fb04b23753 100644 --- a/Lib/test/test_doctest/test_doctest.py +++ b/Lib/test/test_doctest/test_doctest.py @@ -2247,6 +2247,16 @@ def test_DocTestSuite(): >>> suite.run(unittest.TestResult()) + If all examples in a docstring are skipped, unittest will report it as a + skipped test: + + >>> suite = doctest.DocTestSuite('test.test_doctest.sample_doctest_skip') + >>> result = suite.run(unittest.TestResult()) + >>> result + + >>> len(result.skipped) + 2 + We can use the current module: >>> suite = test.test_doctest.sample_doctest.test_suite() @@ -2418,6 +2428,18 @@ def test_DocFileSuite(): Traceback (most recent call last): ValueError: Package may only be specified for module-relative paths. + If all examples in a file are skipped, unittest will report it as a + skipped test: + + >>> suite = doctest.DocFileSuite('test_doctest.txt', + ... 'test_doctest4.txt', + ... 'test_doctest_skip.txt') + >>> result = suite.run(unittest.TestResult()) + >>> result + + >>> len(result.skipped) + 1 + You can specify initial global variables: >>> suite = doctest.DocFileSuite('test_doctest.txt', diff --git a/Lib/test/test_doctest/test_doctest_skip.txt b/Lib/test/test_doctest/test_doctest_skip.txt new file mode 100644 index 00000000000000..f340e2b8141253 --- /dev/null +++ b/Lib/test/test_doctest/test_doctest_skip.txt @@ -0,0 +1,4 @@ +This is a sample doctest in a text file, in which all examples are skipped. + + >>> 2 + 2 # doctest: +SKIP + 5 diff --git a/Misc/NEWS.d/next/Library/2024-03-27-16-43-42.gh-issue-117294.wbXNFv.rst b/Misc/NEWS.d/next/Library/2024-03-27-16-43-42.gh-issue-117294.wbXNFv.rst new file mode 100644 index 00000000000000..bb351e6399a765 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-03-27-16-43-42.gh-issue-117294.wbXNFv.rst @@ -0,0 +1,2 @@ +A ``DocTestCase`` now reports as skipped if all examples in the doctest are +skipped. From e37c1a967306aacd3d63f8043f181fa162d2a047 Mon Sep 17 00:00:00 2001 From: Malcolm Smith Date: Wed, 27 Mar 2024 18:37:38 +0000 Subject: [PATCH 2/3] Add additional test cases; fix test_zipimport_support --- Lib/test/test_doctest/sample_doctest_skip.py | 22 +++++++++++++++----- Lib/test/test_doctest/test_doctest.py | 2 +- Lib/test/test_zipimport_support.py | 4 ++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_doctest/sample_doctest_skip.py b/Lib/test/test_doctest/sample_doctest_skip.py index b140cb2a4a70a2..1b83dec1f8c4dc 100644 --- a/Lib/test/test_doctest/sample_doctest_skip.py +++ b/Lib/test/test_doctest/sample_doctest_skip.py @@ -3,13 +3,18 @@ This module includes various scenarios involving skips. """ -# This test will pass. -def no_skip(): +def no_skip_pass(): """ >>> 2 + 2 4 """ +def no_skip_fail(): + """ + >>> 2 + 2 + 5 + """ + def single_skip(): """ >>> 2 + 2 # doctest: +SKIP @@ -24,8 +29,15 @@ def double_skip(): 6 """ -# This test will fail. -def partial_skip(): +def partial_skip_pass(): + """ + >>> 2 + 2 # doctest: +SKIP + 4 + >>> 3 + 3 + 6 + """ + +def partial_skip_fail(): """ >>> 2 + 2 # doctest: +SKIP 4 @@ -34,4 +46,4 @@ def partial_skip(): """ def no_examples(): - """A docstring with no examples should not be counted as a skip.""" + """A docstring with no examples should not be counted as run or skipped.""" diff --git a/Lib/test/test_doctest/test_doctest.py b/Lib/test/test_doctest/test_doctest.py index 9ec8fb04b23753..8737618018785d 100644 --- a/Lib/test/test_doctest/test_doctest.py +++ b/Lib/test/test_doctest/test_doctest.py @@ -2253,7 +2253,7 @@ def test_DocTestSuite(): >>> suite = doctest.DocTestSuite('test.test_doctest.sample_doctest_skip') >>> result = suite.run(unittest.TestResult()) >>> result - + >>> len(result.skipped) 2 diff --git a/Lib/test/test_zipimport_support.py b/Lib/test/test_zipimport_support.py index 71039d2a8e7ab9..ae8a8c99762313 100644 --- a/Lib/test/test_zipimport_support.py +++ b/Lib/test/test_zipimport_support.py @@ -31,7 +31,7 @@ # Retrieve some helpers from other test cases from test.test_doctest import (test_doctest, sample_doctest, sample_doctest_no_doctests, - sample_doctest_no_docstrings) + sample_doctest_no_docstrings, sample_doctest_skip) def _run_object_doctest(obj, module): @@ -110,7 +110,7 @@ def test_doctest_issue4197(self): # 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]: + sample_doctest_no_docstrings, sample_doctest_skip]: src = inspect.getsource(mod) src = src.replace("test.test_doctest.test_doctest", "test_zipped_doctest") # Rewrite the module name so that, for example, From 9a84cfa3f57f1b7bdd6eef905d5803ffb75d7d53 Mon Sep 17 00:00:00 2001 From: Malcolm Smith Date: Wed, 27 Mar 2024 19:30:31 +0000 Subject: [PATCH 3/3] Remove unnecessary f-string --- Lib/doctest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/doctest.py b/Lib/doctest.py index cac50f9d23439a..fc3f070ef23cc1 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -2264,7 +2264,7 @@ def runTest(self): runner.DIVIDER = "-"*70 results = runner.run(test, out=new.write, clear_globs=False) if results.skipped == results.attempted: - raise unittest.SkipTest(f"all examples were skipped") + raise unittest.SkipTest("all examples were skipped") finally: sys.stdout = old