CQ007: DoctestCheck
Overview
| Property | Value |
|---|---|
| ID | CQ007 |
| Name | DoctestCheck |
| Group | code-quality |
| Severity | WARNING |
Description
Verifies that doctest examples in docstrings execute correctly.
Doctests serve dual purposes:
- Documentation: Show users exactly how to use functions with expected output
- Verification: Ensure examples remain accurate as code evolves
This check ensures your documentation examples actually work.
What it checks
The check scans all Python files in the package (excluding tests and hidden directories), extracts doctest examples from docstrings, and runs them:
- PASSED: All doctest examples produce expected output
- FAILED: One or more examples fail (wrong output or exceptions)
- NOT_APPLICABLE: No doctest examples found in the package
How to fix
Run doctests manually
# Run doctests on a specific file
python -m doctest -v src/mypackage/module.py
# Run doctests on all files
python -m pytest --doctest-modules src/Fix incorrect expected output
# Before (wrong expected output)
def add(a: int, b: int) -> int:
"""Add two numbers.
Examples:
>>> add(1, 2)
4
"""
return a + b
# After (correct expected output)
def add(a: int, b: int) -> int:
"""Add two numbers.
Examples:
>>> add(1, 2)
3
"""
return a + bUse ellipsis for variable output
For output that varies (memory addresses, timestamps, etc.), use # doctest: +ELLIPSIS:
def get_object():
"""Get an object.
Examples:
>>> get_object() # doctest: +ELLIPSIS
<__main__.MyClass object at 0x...>
"""
return MyClass()Handle dictionary output
Dictionary output order may vary. Use ellipsis or normalize:
def get_config():
"""Get configuration.
Examples:
>>> sorted(get_config().items())
[('a', 1), ('b', 2)]
"""
return {'a': 1, 'b': 2}Skip doctests conditionally
For platform-specific or optional-dependency doctests:
def windows_only():
"""Windows-specific function.
Examples:
>>> windows_only() # doctest: +SKIP
'windows result'
"""
...Common doctest directives
| Directive | Purpose |
|---|---|
+ELLIPSIS |
Match ... in output |
+NORMALIZE_WHITESPACE |
Ignore whitespace differences |
+SKIP |
Skip this example |
+IGNORE_EXCEPTION_DETAIL |
Match exception type only |
Writing good doctests
Do
def greet(name: str) -> str:
"""Return a greeting.
Examples:
>>> greet("World")
'Hello, World!'
>>> greet("Python")
'Hello, Python!'
"""
return f"Hello, {name}!"Avoid
def greet(name: str) -> str:
"""Return a greeting.
Examples:
>>> # This is fragile - relies on external state
>>> import os; os.environ['NAME'] = 'Test'
>>> greet(os.environ['NAME'])
'Hello, Test!'
"""
return f"Hello, {name}!"Configuration
Skip patterns
Skip specific files from doctest checking:
[tool.pycmdcheck.checks.CQ007]
skip_patterns = [
"**/conftest.py",
"**/migrations/*.py",
]Skip this check
[tool.pycmdcheck]
skip = ["CQ007"]CLI
pycmdcheck --skip CQ007