The doctest2 module searches for pieces of text that look like interactive sessions, and executes them to verify that they behave as shown in the session. Here are some ways doctest2‘s predecessor, doctest, has been used in the past:
Unlike doctest, doctest2 supports more than just Python. It also supports Unix sh and Windows cmd, and will support other languages in the future.
By and large, doctest2 is backwards compatible. All, or nearly all, examples should be tested and compared in the same way. In cases where they are run differently, doctest2 aims to be “better”, and never break anything. (However, some tests that failed before – incorrectly – may pass under doctest2)
To run doctest2 on a file, use python -m doctest2 my_file, or use the invocation API specified later below.
The classic failure case of doctest is that dicts aren’t ordered, so that the following doctest may fail:
>>> {-1: 0, 1: 2}
{-1: 0, 1: 2}
doctest2 adds a Python literal evaluation mode which takes the entire output of a function, and the expected output, and parses each as a Python literal. In this way, the example is less fragile:
>>> {-1: 0, 1: 2}
{-1: 0, 1: 2}
Often a certain option will be common throughout an entire example session, or a large part of it. doctest2 adds session-global doctest options. Where regular options are given as +FOO, global options are given as +!FOO. For example:
>>> 1
2
>>> 1/0
>>> 0/0 # this is the last skipped doctest before...
>>> 1
1
One of the more noticeable omissions in doctest is the inability to write a testable example of using a function that prints some output before it raises an exception. doctest2 allows you to specify both output _and_ exception:
>>> print('Hello, world!'); 1/0
Hello, world!
Traceback (most recent call last):
...
ZeroDivisionError: integer division or modulo by zero
The most significant addition doctest2 makes to doctest is the ability to test more than just Python interactive sessions. doctest2 can also test example shell sessions, too!
Doctest directives look something like this:
>>> print(1)
1
This could be copy-pasted from an interactive Python session. When passed to doctest2, doctest2 executes the statement print(1) and checks whether the output is 1.
Extending over to multiple lines is done the same as in the interactive interpreter:
>>> print(
... 1)
1
doctest2‘s biggest change is that interactive sessions are no longer limited to Python. In particular, POSIX sh and Windows cmd have been added, and both use a different prompt value. Where Python doctests use >>> and ..., sh doctests use $ and >, and cmd doctests use cmd> and ?. For example:
$ python3 -c "print(1)"
1
cmd> python3 -c "print(1)"
1
This does a similar check, but runs it against sh and cmd.
Note
cmd support is a little shaky, and probably always will be. Even the lowest common denominator shell, sh, offers some features that cmd does not. (For example: inline comments, and parsing error detection)
When requesting that doctest2 run a file to test, the languages that are to be tested must also be tested. In general, doctest2 will default to checking as many language as it knows about. If only _some_ should be tested, doctest2 needs to know which ones.
The doctest2.languages package contains the various languages doctest can understand. For now, that is python (specifically, Python 3.x), sh, and cmd. Each language is represented by an object that doctest2 can use to handle doctests in that language (doctest2.languages.sh, doctest2.languages.cmd, doctest2.languages.python). A list of all available language objects is available at doctest2.languages.languages.
The move to supporting multiple languages comes with some cost in flexibility. In doctest, every doctest function accepted an instantiated finder or parser parameter that emulated doctest2.DocTestFinder or doctest2.DocTestParser respectively. This doesn’t work in doctest2, because these classes don’t know how different languages parse.
In addition some arguments that used to make sense for all doctests only make sense for some. The globs parameter does not make sense for and isn’t used for shell tests. This will be changed around in the future.
Test examples in docstrings reachable from module m, starting with m.__doc__. Also test examples reachable from dict m.__test__ if it exists and is not None.
m.__test__ maps names to functions, classes and strings; function and class docstrings are tested even if the name is private; strings are tested directly, as if they were docstrings.
Parameters: |
|
---|---|
Returns: | (num_failures, num_attempts) |
Return type: | tuple of (int, int) |
Raises : | doctest2.DocTestFailure when raise_on_error is enabled and a doctest fails. |
Raises : | doctest2.UnexpectedException when raise_on_error is enabled and a doctest raises an exception that wasn’t expected. |
Test examples in the given file.
Parameters: |
|
---|---|
Returns: | (num_failures, num_attempts) |
Return type: | tuple of (int, int) |
Raises : | doctest2.DocTestFailure when raise_on_error is enabled and a doctest fails. |
Raises : | doctest2.UnexpectedException when raise_on_error is enabled and a doctest raises an exception that wasn’t expected. |
Test examples in the given object’s docstring (f), without recursing into attributes.
Parameters: |
|
---|---|
Returns: | (num_failures, num_attempts) |
Return type: | tuple of (int, int) |