diff options
Diffstat (limited to 'Lib/test/test_doctest.py')
| -rw-r--r-- | Lib/test/test_doctest.py | 100 |
1 files changed, 57 insertions, 43 deletions
diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index 9292d92..33163b9 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -4,6 +4,7 @@ Test script for doctest. from test import support import doctest +import functools import os import sys @@ -323,7 +324,7 @@ containing test: >>> test.lineno + e2.lineno 26 -If the docstring contains inconsistant leading whitespace in the +If the docstring contains inconsistent leading whitespace in the expected output of an example, then `DocTest` will raise a ValueError: >>> docstring = r''' @@ -434,7 +435,7 @@ We'll simulate a __file__ attr that ends in pyc: >>> tests = finder.find(sample_func) >>> print(tests) # doctest: +ELLIPSIS - [<DocTest sample_func from ...:18 (1 example)>] + [<DocTest sample_func from ...:19 (1 example)>] The exact name depends on how test_doctest was invoked, so allow for leading path components. @@ -658,7 +659,7 @@ plain ol' Python and is guaranteed to be available. >>> import builtins >>> tests = doctest.DocTestFinder().find(builtins) - >>> 790 < len(tests) < 800 # approximate number of objects with docstrings + >>> 790 < len(tests) < 810 # approximate number of objects with docstrings True >>> real_tests = [t for t in tests if len(t.examples) > 0] >>> len(real_tests) # objects that actually have doctests @@ -2096,22 +2097,9 @@ def test_DocTestSuite(): >>> suite.run(unittest.TestResult()) <unittest.result.TestResult run=0 errors=0 failures=0> - However, if DocTestSuite finds no docstrings, it raises an error: + The module need not contain any docstrings either: - >>> 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 = doctest.DocTestSuite('test.sample_doctest_no_docstrings') >>> suite.run(unittest.TestResult()) <unittest.result.TestResult run=0 errors=0 failures=0> @@ -2121,6 +2109,22 @@ def test_DocTestSuite(): >>> suite.run(unittest.TestResult()) <unittest.result.TestResult run=9 errors=0 failures=4> + We can also provide a DocTestFinder: + + >>> finder = doctest.DocTestFinder() + >>> suite = doctest.DocTestSuite('test.sample_doctest', + ... test_finder=finder) + >>> suite.run(unittest.TestResult()) + <unittest.result.TestResult run=9 errors=0 failures=4> + + The DocTestFinder need not return any tests: + + >>> finder = doctest.DocTestFinder() + >>> 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 supply global variables. If we pass globs, they will be used instead of the module globals. Here we'll pass an empty globals, triggering an extra error: @@ -2168,7 +2172,7 @@ def test_DocTestSuite(): >>> test.test_doctest.sillySetup Traceback (most recent call last): ... - AttributeError: 'module' object has no attribute 'sillySetup' + AttributeError: module 'test.test_doctest' has no attribute 'sillySetup' The setUp and tearDown functions are passed test objects. Here we'll use the setUp function to supply the missing variable y: @@ -2314,7 +2318,7 @@ def test_DocFileSuite(): >>> test.test_doctest.sillySetup Traceback (most recent call last): ... - AttributeError: 'module' object has no attribute 'sillySetup' + AttributeError: module 'test.test_doctest' has no attribute 'sillySetup' The setUp and tearDown functions are passed test objects. Here, we'll use a setUp function to set the favorite color in @@ -2361,6 +2365,22 @@ def test_trailing_space_in_test(): foo \n """ +class Wrapper: + def __init__(self, func): + self.func = func + functools.update_wrapper(self, func) + + def __call__(self, *args, **kwargs): + self.func(*args, **kwargs) + +@Wrapper +def test_look_in_unwrapped(): + """ + Docstrings in wrapped functions must be detected as well. + + >>> 'one other test' + 'one other test' + """ def test_unittest_reportflags(): """Default unittest reporting flags can be set to control reporting @@ -2627,7 +2647,7 @@ Windows line endings first: >>> with open(fn, 'wb') as f: ... f.write(b'Test:\r\n\r\n >>> x = 1 + 1\r\n\r\nDone.\r\n') 35 - >>> doctest.testfile(fn, False) + >>> doctest.testfile(fn, module_relative=False, verbose=False) TestResults(failed=0, attempted=1) >>> os.remove(fn) @@ -2637,7 +2657,7 @@ And now *nix line endings: >>> with open(fn, 'wb') as f: ... f.write(b'Test:\n\n >>> x = 1 + 1\n\nDone.\n') 30 - >>> doctest.testfile(fn, False) + >>> doctest.testfile(fn, module_relative=False, verbose=False) TestResults(failed=0, attempted=1) >>> os.remove(fn) @@ -2699,18 +2719,12 @@ output into something we can doctest against: >>> def normalize(s): ... return '\n'.join(s.decode().splitlines()) -Note: we also pass TERM='' to all the assert_python calls to avoid a bug -in the readline library that is triggered in these tests because we are -running them in a new python process. See: - - http://lists.gnu.org/archive/html/bug-readline/2013-06/msg00000.html - With those preliminaries out of the way, we'll start with a file with two simple tests and no errors. We'll run both the unadorned doctest command, and the verbose version, and then check the output: - >>> from test import script_helper - >>> with script_helper.temp_dir() as tmpdir: + >>> from test.support import script_helper, temp_dir + >>> with temp_dir() as tmpdir: ... fn = os.path.join(tmpdir, 'myfile.doc') ... with open(fn, 'w') as f: ... _ = f.write('This is a very simple test file.\n') @@ -2721,9 +2735,9 @@ the verbose version, and then check the output: ... _ = f.write('\n') ... _ = f.write('And that is it.\n') ... rc1, out1, err1 = script_helper.assert_python_ok( - ... '-m', 'doctest', fn, TERM='') + ... '-m', 'doctest', fn) ... rc2, out2, err2 = script_helper.assert_python_ok( - ... '-m', 'doctest', '-v', fn, TERM='') + ... '-m', 'doctest', '-v', fn) With no arguments and passing tests, we should get no output: @@ -2755,13 +2769,13 @@ Now we'll write a couple files, one with three tests, the other a python module with two tests, both of the files having "errors" in the tests that can be made non-errors by applying the appropriate doctest options to the run (ELLIPSIS in the first file, NORMALIZE_WHITESPACE in the second). This combination will -allow to thoroughly test the -f and -o flags, as well as the doctest command's +allow thoroughly testing the -f and -o flags, as well as the doctest command's ability to process more than one file on the command line and, since the second file ends in '.py', its handling of python module files (as opposed to straight text files). - >>> from test import script_helper - >>> with script_helper.temp_dir() as tmpdir: + >>> from test.support import script_helper, temp_dir + >>> with temp_dir() as tmpdir: ... fn = os.path.join(tmpdir, 'myfile.doc') ... with open(fn, 'w') as f: ... _ = f.write('This is another simple test file.\n') @@ -2786,17 +2800,17 @@ text files). ... _ = f.write(' \"\"\"\n') ... import shutil ... rc1, out1, err1 = script_helper.assert_python_failure( - ... '-m', 'doctest', fn, fn2, TERM='') + ... '-m', 'doctest', fn, fn2) ... rc2, out2, err2 = script_helper.assert_python_ok( - ... '-m', 'doctest', '-o', 'ELLIPSIS', fn, TERM='') + ... '-m', 'doctest', '-o', 'ELLIPSIS', fn) ... rc3, out3, err3 = script_helper.assert_python_ok( ... '-m', 'doctest', '-o', 'ELLIPSIS', - ... '-o', 'NORMALIZE_WHITESPACE', fn, fn2, TERM='') + ... '-o', 'NORMALIZE_WHITESPACE', fn, fn2) ... rc4, out4, err4 = script_helper.assert_python_failure( - ... '-m', 'doctest', '-f', fn, fn2, TERM='') + ... '-m', 'doctest', '-f', fn, fn2) ... rc5, out5, err5 = script_helper.assert_python_ok( ... '-m', 'doctest', '-v', '-o', 'ELLIPSIS', - ... '-o', 'NORMALIZE_WHITESPACE', fn, fn2, TERM='') + ... '-o', 'NORMALIZE_WHITESPACE', fn, fn2) Our first test run will show the errors from the first file (doctest stops if a file has errors). Note that doctest test-run error output appears on stdout, @@ -2902,7 +2916,7 @@ We should also check some typical error cases. Invalid file name: >>> rc, out, err = script_helper.assert_python_failure( - ... '-m', 'doctest', 'nosuchfile', TERM='') + ... '-m', 'doctest', 'nosuchfile') >>> rc, out (1, b'') >>> print(normalize(err)) # doctest: +ELLIPSIS @@ -2913,7 +2927,7 @@ Invalid file name: Invalid doctest option: >>> rc, out, err = script_helper.assert_python_failure( - ... '-m', 'doctest', '-o', 'nosuchoption', TERM='') + ... '-m', 'doctest', '-o', 'nosuchoption') >>> rc, out (2, b'') >>> print(normalize(err)) # doctest: +ELLIPSIS @@ -2927,7 +2941,7 @@ Invalid doctest option: def test_main(): # Check the doctest cases in doctest itself: - support.run_doctest(doctest, verbosity=True) + ret = support.run_doctest(doctest, verbosity=True) # Check the doctest cases defined here: from test import test_doctest support.run_doctest(test_doctest, verbosity=True) |
