doctest en Python: prueba ejemplos

Publicado el: 15/08/2026
Tempo de leitura: 5 minutos
Portátil con código que representa ejemplos ejecutables probados con doctest en Python

El módulo doctest en Python encuentra texto que parece una sesión interactiva dentro de docstrings o archivos de documentación, ejecuta cada comando y compara la salida real con la documentada. Convierte ejemplos en documentación ejecutable y ayuda a mantener tutoriales, ayuda y snippets sincronizados con el código.

Funciona mejor con ejemplos pequeños, deterministas y fáciles de leer. No sustituye una suite completa, especialmente para estados complejos, red, concurrencia, fixtures elaboradas o reglas que necesitan aserciones detalladas.

Escribe el primer ejemplo

Una docstring puede incluir prompts >>> seguidos de la salida esperada.

def doble(valor):
    """Devuelve el doble.

    >>> doble(4)
    8
    >>> doble(-3)
    -6
    """
    return valor * 2

El texto sigue las convenciones de una sesión interactiva. La salida comienza inmediatamente después del comando y termina ante otro prompt o una línea vacía.

Ejecuta con testmod

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

Al ejecutar el archivo, no ver salida significa que todos los ejemplos pasaron. Usa modo detallado para observar cada intento:

python modulo.py -v

En CI, comprueba el resultado o integra doctest con unittest para que una configuración incorrecta no parezca éxito.

Usa la línea de comandos

python -m doctest modulo.py
python -m doctest -v modulo.py

Pasar un miembro de paquete como archivo aislado puede romper imports relativos. En paquetes, suele ser mejor importarlo dentro del contexto correcto.

Prueba archivos de documentación

testfile() lee ejemplos interactivos de un archivo textual.

import doctest

resultado = doctest.testfile(
    "guia.txt",
    module_relative=False,
)
print(resultado)

El archivo se trata como una docstring grande, lo que permite verificar tutoriales sin colocar todos los ejemplos en el código.

Comprende el contexto

Cada docstring recibe normalmente una copia superficial de los globals del módulo. Ejemplos dentro de la misma docstring comparten nombres; docstrings diferentes normalmente no.

def ejemplo_estado():
    """
    >>> valores = [1, 2]
    >>> valores.append(3)
    >>> valores
    [1, 2, 3]
    """

Una copia superficial todavía comparte objetos mutables referenciados. Evita estado global real y limpia archivos, variables y conexiones.

Proporciona globals explícitos

globs y extraglobs preparan nombres.

doctest.testfile(
    "ejemplos.txt",
    globs={"Cliente": Cliente},
    extraglobs={"config": config_prueba},
    module_relative=False,
)

No inyectes credenciales de producción, sesiones reales ni recursos irreversibles. Usa fakes y directorios temporales.

Documenta excepciones

Un ejemplo puede incluir el traceback esperado. Las líneas intermedias suelen ignorarse y se compara el tipo y detalle.

def dividir(a, b):
    """
    >>> dividir(10, 0)
    Traceback (most recent call last):
    ...
    ZeroDivisionError: division by zero
    """
    return a / b

Si el mensaje cambia entre versiones, IGNORE_EXCEPTION_DETAIL permite centrarse en el tipo. Úsalo solo cuando el texto no sea parte del contrato.

Normaliza espacios

NORMALIZE_WHITESPACE considera equivalentes las secuencias de espacios y saltos.

>>> print(list(range(10)))  # doctest: +NORMALIZE_WHITESPACE
[0, 1, 2, 3, 4,
 5, 6, 7, 8, 9]

Aplica la directiva solo donde el formato sea irrelevante. Activarla globalmente puede ocultar regresiones.

Usa ELLIPSIS con cuidado

ELLIPSIS permite que ... coincida con cualquier fragmento.

>>> objeto
<MiObjeto id=...>  # doctest: +ELLIPSIS

Mantén prefijos y sufijos estables. Una elipsis demasiado amplia puede aceptar una salida equivocada.

Representa líneas vacías

Una línea vacía termina la salida esperada. Para exigir una línea en blanco, escribe <BLANKLINE>.

>>> print("primera\n\ntercera")
primera
<BLANKLINE>
tercera

Esta regla causa muchos fallos al copiar salida multilínea.

Evita orden no determinista

No compares sets o mappings cuyo orden no sea parte de la API.

>>> sorted(obtener_tags())
['api', 'python', 'prueba']

Formatea floats explícitamente. Evita timestamps, direcciones de memoria, UUID aleatorios, rutas temporales y mensajes dependientes de plataforma.

Añade ejemplos con __test__

Un mapping __test__ permite añadir casos que no aparecen en la ayuda principal.

__test__ = {
    "casos_extra": """
    >>> doble(0)
    0
    """,
}

Los valores pueden ser strings, funciones o clases y sus docstrings se examinan.

Qué objetos se buscan

testmod() examina docstring del módulo, funciones, clases, métodos y objetos de __test__. Los objetos importados desde otros módulos no se buscan automáticamente.

La guía de pydoc en Python explica la visualización de documentación. Para listar clases y funciones sin importar, consulta pyclbr en Python.

Integra con unittest

DocTestSuite() convierte ejemplos de un módulo en una suite unittest.

import doctest
import unittest
import mi_modulo


def load_tests(loader, tests, pattern):
    tests.addTests(doctest.DocTestSuite(mi_modulo))
    return tests

if __name__ == "__main__":
    unittest.main()

DocFileSuite() hace lo mismo para archivos de texto. Así la ejecución y los reportes quedan integrados.

Prepara y limpia recursos

Las suites aceptan setUp y tearDown.

def preparar(test):
    test.globs["repositorio"] = RepositorioTemporal()


def limpiar(test):
    test.globs["repositorio"].close()

suite = doctest.DocTestSuite(
    mi_modulo,
    setUp=preparar,
    tearDown=limpiar,
)

La limpieza debe ocurrir incluso tras fallos. Prefiere tempfile, mocks y recursos en memoria.

FAIL_FAST y reportes

La opción -f activa FAIL_FAST. Otras flags muestran diferencias unificadas, de contexto o dentro de líneas.

python -m doctest -v -f guia.txt

Fallar pronto ayuda durante depuración. En CI puede ser mejor informar todos los ejemplos rotos.

Omite casos deliberadamente

>>> abrir_navegador()  # doctest: +SKIP

SKIP sirve para ejemplos ilustrativos o servicios no disponibles. Revisa los skips porque pueden ocultar documentación rota.

Analiza ejemplos programáticamente

DocTestParser extrae objetos Example.

from doctest import DocTestParser

texto = """
>>> 2 + 2
4
"""
ejemplos = DocTestParser().get_examples(texto)
print(ejemplos[0].source, ejemplos[0].want)

DocTestFinder, DocTestRunner y OutputChecker permiten integraciones personalizadas. Usa la API básica salvo necesidad real.

Seguridad

Doctest ejecuta los ejemplos encontrados. Nunca ejecutes documentación enviada por usuarios, paquetes desconocidos o repositorios no confiables en el proceso principal.

Usa un proceso o contenedor restringido, timeout, límites de memoria y CPU, sin credenciales de producción, con filesystem temporal y red controlada. Importar el módulo ya puede ejecutar código superior.

Tracebacks y diagnósticos

La guía de traceback en Python explica el formato de excepciones. En doctest, incluye solo detalles estables y evita rutas y líneas.

Introspección y documentación

inspect en Python ayuda a recuperar firmas y docstrings antes de construir suites. La introspección de objetos vivos suele exigir importar el código.

Cuándo no usar doctest

  • Flujos largos con fixtures complejas.
  • Salidas grandes o inestables.
  • Pruebas de concurrencia y tiempo.
  • Integraciones reales de red y base de datos.
  • Property testing con muchos valores.
  • Reglas críticas con aserciones detalladas.

Usa unittest, pytest o herramientas especializadas y deja doctest para ejemplos públicos.

Buenas prácticas

  • Mantén ejemplos cortos y deterministas.
  • Prueba comportamiento público.
  • Ordena colecciones antes de mostrarlas.
  • Formatea floats explícitamente.
  • Usa directivas localmente.
  • Evita elipsis excesivas.
  • Ejecuta documentación en CI.
  • Aísla documentación no confiable.

Conclusión

doctest en Python mantiene ejemplos sincronizados y convierte documentación en pruebas ejecutables. Es excelente para APIs pequeñas, tutoriales y regresiones legibles cuando la salida es estable.

Consulta la documentación oficial de doctest y la documentación de unittest.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Código en pantalla que representa navegación de clases y funciones con pyclbr en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pyclbr en Python: inspecciona módulos

    Aprende pyclbr en Python para listar clases, funciones, métodos y definiciones anidadas sin importar ni ejecutar el módulo.

    Ler mais

    Tempo de leitura: 5 minutos
    15/08/2026
    Monitor con código binario que representa instrucciones opcode del bytecode de Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    opcode en Python: explora el bytecode

    Aprende opcode en Python para mapear instrucciones de bytecode, argumentos, saltos, caches y efectos de pila mediante dis.

    Ler mais

    Tempo de leitura: 5 minutos
    15/08/2026
    Desarrollador investigando consumo de memoria con tracemalloc en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    tracemalloc en Python: detecta fugas

    Usa tracemalloc en Python para comparar snapshots, localizar crecimiento de memoria e investigar fugas en aplicaciones.

    Ler mais

    Tempo de leitura: 6 minutos
    15/08/2026
    Código con anotaciones de tipos que representa introspección con annotationlib en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    annotationlib en Python: lee anotaciones

    Aprende annotationlib en Python 3.14 para recuperar anotaciones como valores, ForwardRef o strings y controlar riesgos de ejecución.

    Ler mais

    Tempo de leitura: 5 minutos
    14/08/2026
    Archivadores organizados que representan módulos importados directamente desde archivos ZIP con zipimport en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    zipimport en Python: importa desde ZIP

    Aprende zipimport en Python para cargar módulos y paquetes desde archivos ZIP, usar importadores y proteger sistemas de plugins.

    Ler mais

    Tempo de leitura: 5 minutos
    14/08/2026
    Diagrama de directorios que representa rutas site-packages y configuración del módulo site en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    site en Python: entiende las rutas

    Aprende el módulo site en Python para entender site-packages, user site, archivos .pth, sitecustomize, usercustomize y opciones de inicio.

    Ler mais

    Tempo de leitura: 7 minutos
    14/08/2026