Embedding doctests into docstrings

It's just as easy to write doctests into docstrings as it is to write them into documentation files.

Note

For those who don't know, docstrings are a Python feature that allows programmers to embed documentation directly into their source code. The Python help() function is powered by docstrings. To learn more about docstrings, you can start with the Python tutorial section at https://docs.python.org/3/tutorial/controlflow.html#documentation-strings.

When written in docstrings, doctests serve a slightly different purpose. They still let the computer check that things work as expected, but the humans who see them will most often be coders who use the Python interactive shell to work on an idea before committing it to code, or whose text editor pops up docstrings as they work. In that context, the most important thing a doctest can do is be informative, so docstrings aren't usually a good place for checking picky details. They're a great place for a doctest to demonstrate the proper behavior of a common case, though.

The doctests embedded in docstrings have a somewhat different execution scope than doctests in text files do. Instead of having a single scope for all of the tests in the file, doctest creates a single scope for each docstring. All of the tests that share a docstring also share an execution scope, but they're isolated from tests in the other docstrings.

The separation of each docstring into its own execution scope often means that we don't need to put much thought into isolating doctests when they're embedded in docstrings. This is fortunate, since docstrings are primarily intended for documentation, and the tricks required to isolate the tests might obscure the meaning.

Example – a doctest in a docstring

We're going to embed a test right inside the Python source file that it tests, by placing it inside a docstring.

Create a file called test.py containing the following code:

def testable(x):
    r"""
    The `testable` function returns the square root of its
    parameter, or 3, whichever is larger.

    >>> testable(7)
    3.0

    >>> testable(16)
    4.0

    >>> testable(9)
    3.0

    >>> testable(10) == 10 ** 0.5
    True
    """
    if x < 9:
        return 3.0
    return x ** 0.5

Note

Notice the use of a raw string for the docstring (denoted by the r character before the first triple quote). Using raw strings for your docstrings is a good habit to get into, because you usually don't want escape sequences—for example, for newline— to be interpreted by the Python interpreter. You want them to be treated as text, so that they are correctly passed on to doctest.

Running these tests is just as easy as running the tests in a doctest document:

python3 -m doctest test.py

Since all the tests pass, the output of this command is nothing at all. We can make it more interesting by adding the verbose flag to the command line:

python3 -m doctest -v test.py

Result – the code is now self-documenting and self-testable

When we run the Python file through doctest with the verbose flag, we see the output, as shown in the the following screenshot:

Result – the code is now self-documenting and self-testable

We put the doctest code right inside the docstring of the function it was testing. This is a good place for tests that also show a programmer how to do something. It's not a good place for detailed, low-level tests (the doctest in the docstring example code, which was quite detailed for illustrative purposes, is perhaps too detailed), because docstrings need to serve as API documentation—you can see the reason for this just by looking at the example, where the doctests take up most of the room in the docstring without telling the readers any more than they would have learned from a single test.

Any test that will serve as good API documentation is a good candidate for including in the docstrings of a Python file.

You might be wondering about the line that reads 1 items had no tests, and the following line that just reads test. These lines are referring to the fact that there are no tests written in the module-level docstring. That's a little surprising, since we didn't include such a docstring in our source code at all, until you realize that, as far as Python (and thus doctest) is concerned, no docstring is the same as an empty docstring.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.42.176