Python Doctests: The Complete Guide to Documentation-Driven Testing
Writing documentation is essential, but code examples in documentation frequently rot over time as codebases evolve. Python's built-in doctest module solves this problem by allowing you to write executable code examples directly inside your docstrings. The system verifies that the actual function output matches your documented example output.
By combining doctest (for living documentation correctness) and pytest (as your primary test runner), you get a symbiotic testing strategy that guarantees your code works and your documentation is always truthful.
This guide covers when to use doctests, how to write them, the various ways to execute them, and how to optimize your developer workflow in VS Code and Gitpod.
When and Why to Use Doctestโ
Doctests are not intended to replace comprehensive unit test suites. Instead, they serve as a documentation correctness tool.
The Golden Rules of Doctestingโ
- Use doctests for:
- Deterministic, pure functions (given input $X$, output is always $Y$).
- Reusable utility helpers (e.g., text sanitizers, email validators, unit converters).
- Algorithmic examples where demonstrating usage makes the documentation easier to read.
- Avoid doctests for:
- Side-effect-heavy routines (database integrations, network calls, file system writes).
- Functions requiring complex mocking, fixtures, or environment setup.
- Verifying edge conditions or exception hierarchies (use Pytest for these).
In a typical production application, roughly 10% to 20% of your helper functions are suitable for doctests. The rest should reside in traditional test files.
Writing Your First Doctestโ
To write a doctest, format your docstring examples to mimic an interactive Python shell session using the >>> prefix:
def sanitize_vegetable_name(name: str) -> str:
"""
Removes trailing whitespace and capitalizes the vegetable name.
>>> sanitize_vegetable_name(" carrot ")
'Carrot'
>>> sanitize_vegetable_name("BROCCOLI")
'Broccoli'
"""
return name.strip().capitalize()
Various Ways to Run Doctestsโ
Python and Pytest provide multiple options for executing doctests, depending on your preferred workflow.
1. From the Command Lineโ
To run doctests in a specific file on the fly, invoke the module directly:
python -m doctest -v your_script.py
(The -v verbose flag outputs exactly which examples ran and their statuses).
2. Embedding in the Script Blockโ
You can instruct Python to execute doctests programmatically when running the script directly:
if __name__ == "__main__":
import doctest
doctest.testmod(verbose=True)
3. Testing Separate Text Filesโ
If you write user guides or READMEs in separate .txt or .rst files, you can validate those code blocks directly:
import doctest
doctest.testfile("README.txt", verbose=True)
4. Running specific objectsโ
If you only want to validate the docstrings of a specific function or class:
import doctest
doctest.run_docstring_examples(sanitize_vegetable_name, globals(), verbose=True)
5. Running with Pytest (Recommended)โ
Pytest natively supports collecting and running doctests. Simply run:
pytest --doctest-modules your_script.py
Symbiotic Testing: Pytest + Doctest Integrationโ
Instead of running two separate test suites, configure Pytest to run your unit tests and doctests together.
Configuration in pyproject.tomlโ
Add the --doctest-modules flag to your default Pytest options so it scans all docstrings automatically:
[tool.pytest.ini_options]
addopts = "--doctest-modules"
Pre-commit Validation Hookโ
Add a Git pre-commit hook to verify both unit tests and documentation examples pass locally before code is pushed to your remote repository:
- repo: https://github.com/pre-commit/mirrors-pytest
rev: v7.4.2
hooks:
- id: pytest
IDE Setup in VS Code and Gitpodโ
If you are developing inside Gitpod or VS Code, you can streamline writing doctests:
- Auto-Formatting Docstrings: Use the autoDocstring extension in VS Code. It provides customized templates for docstrings, so you do not have to type the
>>>syntax manually. - Syntax Highlighting: Install a docstring syntax highlighter to color-code code examples within Python docstrings, distinguishing them from standard commentary.
- Save Verification: Always save your changes before running tests from the terminal, as external CLI runners only inspect files committed to disk.
Sourcesโ
- [1] Python Documentation: doctest Standard Library
- [2] Pytest Documentation: How to run doctests
- [3] VS Code Documentation: Python Testing in Visual Studio Code
- [4] Python Documentation: timeit module
- [5] Python Documentation: tracemalloc module
