2025, Dec 04 15:00
How to make Python doctest pass with colored console output using ANSI sequences and colorama
Learn why Python doctest fails on colored output and how to fix it with ANSI code placeholders and colorama-driven docstrings. Keep tests readable and accurate.
Testing console output is usually straightforward with doctest—until color enters the chat. As soon as ANSI sequences show up in stdout, what looks identical to a human stops matching byte-for-byte for the test runner. Below is a concise walkthrough of why doctest fails on colored output and how to make the expected text accurately reflect what is really printed, without sacrificing readability.
The problem
We want to verify printed content. One function prints plain text, another prints the same text wrapped in color. The doctest for the colored variant should focus on the visible content, yet the check fails because the underlying output includes invisible color codes.
from colorama import Fore
def emit_text():
"""Prints out the result.
>>> emit_text()
Hello world
"""
print('Hello world')
def emit_text_with_color():
"""Prints out the result.
>>> emit_text_with_color()
Hello world
"""
print(Fore.GREEN + 'Hello world' + Fore.RESET)
if __name__ == '__main__':
import doctest
doctest.testmod()
When doctest evaluates the second example, it reports a mismatch even though both lines appear identical to the eye.
Why the doctest fails
doctest performs a literal comparison of what your code prints against what is written in the docstring. The colored variant emits the text alongside ANSI escape sequences produced by colorama, while the expected snippet in the docstring is plain text. These invisible sequences make the actual output longer and different, hence the failure.
The solution
Encode color markers directly into the docstring using a lightweight wrapper that fills placeholders with the real control codes before doctest runs. This way, the docstring holds the canonical truth: both visible content and color information are represented explicitly and consistently with the actual runtime output.
from colorama import Fore
def inject_docs(fn):
fn.__doc__ = fn.__doc__.format(**{"GREEN": Fore.GREEN, "RESET": Fore.RESET})
return fn
def emit_text():
"""Prints out the result.
>>> emit_text()
Hello world
"""
print("Hello world")
@inject_docs
def emit_text_with_color():
"""Prints out the result.
>>> emit_text_with_color()
{GREEN}Hello world{RESET}
"""
print(Fore.GREEN + "Hello world" + Fore.RESET)
if __name__ == "__main__":
import doctest
doctest.testmod()
Here the placeholders {GREEN} and {RESET} are substituted with the actual Fore.GREEN and Fore.RESET values before doctest compares outputs. The result is a passing test that remains readable and self-documenting.
Why this matters
Console UX often relies on color to communicate state, severity, or focus. If your doctests ignore color, they risk drifting away from what the program truly emits. If they compare plain text to colored output, they fail for reasons unrelated to the message itself. Encoding the color intent directly in the doctest keeps expectations faithful to reality and prevents subtle breakages when formatting is involved.
For additional background on placing variables into docstrings, see these answers: link.
Conclusion
When doctesting functions that print colored text, treat formatting as part of the contract. Use placeholders in the docstring and expand them at import time to align expected and actual output. This approach keeps doctests precise, keeps documentation truthful, and ensures your tests won’t fail just because the terminal added a little color.