How Python doctest Runs Tests in Docstrings

Python’s built-in doctest module scans your code's documentation strings (docstrings), extracts snippets that look like interactive Python sessions, executes them, and verifies that the output matches the documented results. By treating documentation examples as automated tests, it ensures that your API reference remains both accurate and functional with minimal setup.

How doctest Identifies and Parses Tests

The doctest module searches through modules, classes, methods, and functions to inspect their docstrings. It looks specifically for lines prefixed with the standard Python interactive prompt:

Any text immediately following a line or block of >>> inputs—up to the next prompt, an empty line, or the end of the docstring—is treated as the expected output.

def add(a, b):
    """
    Return the sum of a and b.

    >>> add(2, 3)
    5
    >>> add(-1, 1)
    0
    """
    return a + b

In this example, doctest identifies two separate tests: add(2, 3) with an expected output of 5, and add(-1, 1) with an expected output of 0.

The Execution Mechanism

Once doctest parses the code snippets and their expected outputs, it runs them through an automated execution pipeline:

  1. Namespace Isolation: By default, doctest creates a shallow copy of the target module's global namespace, ensuring tests can access the functions, classes, and imported modules defined in that file.
  2. Evaluation: The extracted code is executed dynamically using Python's runtime evaluation mechanisms (exec() for statements and eval() for expressions).
  3. Stream Interception: Standard output (sys.stdout) is intercepted during execution so that any returned values or printed text are captured as raw strings.
  4. Exception Handling: If an example expects an error, doctest looks for a traceback header (Traceback (most recent call last):) followed by the exception type and message. It checks whether the raised exception matches the documented behavior.

Output Comparison and Directives

doctest performs an exact string comparison between the captured output and the expected output in the docstring. A test passes only if the actual output matches character-for-character, including whitespace and line breaks.

To handle dynamic or variable outputs, doctest supports inline directives that modify comparison rules:

def get_user():
    """
    >>> get_user() # doctest: +ELLIPSIS
    <User object at 0x...>
    """
    pass

Running doctests

You can execute docstring tests directly from the command line without modifying your source code:

python -m doctest -v script.py

The -v (verbose) flag displays every test executed and whether it passed or failed. Without the flag, doctest runs silently and only prints output if a test fails.

Alternatively, you can trigger execution within the script itself by adding a standard entry point:

if __name__ == "__main__":
    import doctest
    doctest.testmod()

When run as a standalone script, doctest.testmod() inspects the current module's docstrings, executes all embedded sessions, and reports failures to standard error.