#11390: convert doctest CLI to argparse and add -o and -f options.

This provides a way to specify arbitrary doctest options when using
the CLI interface to process test files, just as one can when calling
testmod or testfile programmatically.
This commit is contained in:
R David Murray 2013-06-23 14:24:13 -04:00
parent c00fffb659
commit 5707d508e1
5 changed files with 273 additions and 12 deletions

View file

@ -2596,6 +2596,232 @@ Check doctest with a non-ascii filename:
TestResults(failed=1, attempted=1)
"""
def test_CLI(): r"""
The doctest module can be used to run doctests against an arbitrary file.
These tests test this CLI functionality.
We'll use the support module's script_helpers for this, and write a test files
to a temp dir to run the command against.
First, 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:
... fn = os.path.join(tmpdir, 'myfile.doc')
... with open(fn, 'w') as f:
... _ = f.write('This is a very simple test file.\n')
... _ = f.write(' >>> 1 + 1\n')
... _ = f.write(' 2\n')
... _ = f.write(' >>> "a"\n')
... _ = f.write(" 'a'\n")
... _ = f.write('\n')
... _ = f.write('And that is it.\n')
... rc1, out1, err1 = script_helper.assert_python_ok(
... '-m', 'doctest', fn)
... rc2, out2, err2 = script_helper.assert_python_ok(
... '-m', 'doctest', '-v', fn)
With no arguments and passing tests, we should get no output:
>>> rc1, out1, err1
(0, b'', b'')
With the verbose flag, we should see the test output, but no error output:
>>> rc2, err2
(0, b'')
>>> print(out2.decode())
Trying:
1 + 1
Expecting:
2
ok
Trying:
"a"
Expecting:
'a'
ok
1 items passed all tests:
2 tests in myfile.doc
2 tests in 1 items.
2 passed and 0 failed.
Test passed.
<BLANKLINE>
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
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:
... fn = os.path.join(tmpdir, 'myfile.doc')
... with open(fn, 'w') as f:
... _ = f.write('This is another simple test file.\n')
... _ = f.write(' >>> 1 + 1\n')
... _ = f.write(' 2\n')
... _ = f.write(' >>> "abcdef"\n')
... _ = f.write(" 'a...f'\n")
... _ = f.write(' >>> "ajkml"\n')
... _ = f.write(" 'a...l'\n")
... _ = f.write('\n')
... _ = f.write('And that is it.\n')
... fn2 = os.path.join(tmpdir, 'myfile2.py')
... with open(fn2, 'w') as f:
... _ = f.write('def test_func():\n')
... _ = f.write(' \"\"\"\n')
... _ = f.write(' This is simple python test function.\n')
... _ = f.write(' >>> 1 + 1\n')
... _ = f.write(' 2\n')
... _ = f.write(' >>> "abc def"\n')
... _ = f.write(" 'abc def'\n")
... _ = f.write("\n")
... _ = f.write(' \"\"\"\n')
... import shutil
... rc1, out1, err1 = script_helper.assert_python_failure(
... '-m', 'doctest', fn, fn2)
... rc2, out2, err2 = script_helper.assert_python_ok(
... '-m', 'doctest', '-o', 'ELLIPSIS', fn)
... rc3, out3, err3 = script_helper.assert_python_ok(
... '-m', 'doctest', '-o', 'ELLIPSIS',
... '-o', 'NORMALIZE_WHITESPACE', fn, fn2)
... rc4, out4, err4 = script_helper.assert_python_failure(
... '-m', 'doctest', '-f', fn, fn2)
... rc5, out5, err5 = script_helper.assert_python_ok(
... '-m', 'doctest', '-v', '-o', 'ELLIPSIS',
... '-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,
not stderr:
>>> rc1, err1
(1, b'')
>>> print(out1.decode()) # doctest: +ELLIPSIS
**********************************************************************
File "...myfile.doc", line 4, in myfile.doc
Failed example:
"abcdef"
Expected:
'a...f'
Got:
'abcdef'
**********************************************************************
File "...myfile.doc", line 6, in myfile.doc
Failed example:
"ajkml"
Expected:
'a...l'
Got:
'ajkml'
**********************************************************************
1 items had failures:
2 of 3 in myfile.doc
***Test Failed*** 2 failures.
<BLANKLINE>
With -o ELLIPSIS specified, the second run, against just the first file, should
produce no errors, and with -o NORMALIZE_WHITESPACE also specified, neither
should the third, which ran against both files:
>>> rc2, out2, err2
(0, b'', b'')
>>> rc3, out3, err3
(0, b'', b'')
The fourth run uses FAIL_FAST, so we should see only one error:
>>> rc4, err4
(1, b'')
>>> print(out4.decode()) # doctest: +ELLIPSIS
**********************************************************************
File "...myfile.doc", line 4, in myfile.doc
Failed example:
"abcdef"
Expected:
'a...f'
Got:
'abcdef'
**********************************************************************
1 items had failures:
1 of 2 in myfile.doc
***Test Failed*** 1 failures.
<BLANKLINE>
The fifth test uses verbose with the two options, so we should get verbose
success output for the tests in both files:
>>> rc5, err5
(0, b'')
>>> print(out5.decode())
Trying:
1 + 1
Expecting:
2
ok
Trying:
"abcdef"
Expecting:
'a...f'
ok
Trying:
"ajkml"
Expecting:
'a...l'
ok
1 items passed all tests:
3 tests in myfile.doc
3 tests in 1 items.
3 passed and 0 failed.
Test passed.
Trying:
1 + 1
Expecting:
2
ok
Trying:
"abc def"
Expecting:
'abc def'
ok
1 items had no tests:
myfile2
1 items passed all tests:
2 tests in myfile2.test_func
2 tests in 2 items.
2 passed and 0 failed.
Test passed.
<BLANKLINE>
We should also check some typical error cases.
Invalid file name:
>>> rc, out, err = script_helper.assert_python_failure(
... '-m', 'doctest', 'nosuchfile')
>>> rc, out
(1, b'')
>>> print(err.decode()) # doctest: +ELLIPSIS
Traceback (most recent call last):
...
FileNotFoundError: [Errno ...] No such file or directory: 'nosuchfile'
Invalid doctest option:
>>> rc, out, err = script_helper.assert_python_failure(
... '-m', 'doctest', '-o', 'nosuchoption')
>>> rc, out
(2, b'')
>>> print(err.decode()) # doctest: +ELLIPSIS
usage...invalid...nosuchoption...
"""
######################################################################
## Main
######################################################################