doctest no Python: teste exemplos

Publicado em: 15/08/2026
Tempo de leitura: 6 minutos
Notebook com código representando exemplos executáveis testados com doctest no Python

O módulo doctest no Python encontra trechos que parecem sessões interativas dentro de docstrings ou arquivos de texto, executa cada comando e compara a saída real com a saída documentada. Ele transforma exemplos em documentação executável e ajuda a impedir que tutoriais, mensagens de ajuda e snippets fiquem desatualizados.

O recurso funciona melhor com exemplos pequenos, determinísticos e fáceis de ler. Ele não substitui uma suíte completa de testes, especialmente para lógica complexa, estados compartilhados, integração com rede ou casos que exigem fixtures elaboradas.

Escreva o primeiro exemplo

Uma docstring pode incluir prompts >>> e a saída esperada.

def dobro(valor):
    """Retorna o dobro de um número.

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

O texto precisa imitar uma sessão interativa. A saída esperada começa logo após o comando e termina quando aparece outro prompt ou uma linha em branco.

Execute com testmod

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

Ao executar o arquivo, nenhuma saída significa que todos os exemplos passaram. Use modo verboso para acompanhar cada tentativa:

python modulo.py -v

Em CI, verifique o código de saída ou use a integração com unittest para evitar sucesso silencioso após uma configuração incorreta.

Use a linha de comando

Também é possível executar o módulo diretamente:

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

Para arquivos que fazem parte de um pacote e usam imports relativos, importar o módulo pelo contexto correto costuma ser mais confiável do que passar um arquivo isolado.

Teste arquivos de documentação

testfile() lê exemplos de um arquivo textual, como Markdown ou reStructuredText.

import doctest

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

O arquivo é tratado como uma docstring gigante. Isso permite testar tutoriais sem colocar todos os exemplos no código-fonte.

Entenda o contexto de execução

Cada docstring normalmente recebe uma cópia rasa dos globais do módulo. Exemplos dentro da mesma docstring compartilham variáveis; exemplos de docstrings diferentes não compartilham o mesmo contexto.

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

Objetos mutáveis presentes no dicionário copiado ainda podem ser compartilhados por referência. Evite depender de estado global e limpe recursos após cada teste.

Forneça globais explícitos

globs e extraglobs permitem preparar nomes.

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

Não inclua credenciais reais, conexões de produção ou objetos com efeitos irreversíveis. Use doubles, diretórios temporários e configurações de teste.

Teste exceções

Um exemplo pode documentar o traceback esperado. A pilha intermediária é normalmente ignorada; o tipo e a mensagem são comparados.

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

Quando mensagens variam entre versões, use IGNORE_EXCEPTION_DETAIL com cuidado. Ainda é importante confirmar o tipo correto da exceção.

Normalize espaços

NORMALIZE_WHITESPACE considera sequências de espaços e quebras equivalentes.

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

Não ative a opção globalmente para esconder formatação que faz parte do contrato. Aplique diretivas somente nos exemplos necessários.

Use ELLIPSIS com moderação

ELLIPSIS permite que ... corresponda a qualquer trecho.

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

Uma elipse muito ampla pode aceitar uma saída errada. Mantenha partes estáveis antes e depois do marcador.

Linhas em branco

Uma linha vazia encerra o bloco de saída esperada. Para exigir uma linha em branco, escreva <BLANKLINE>.

>>> print("primeira\n\nterceira")
primeira
<BLANKLINE>
terceira

Essa regra frequentemente causa falhas ao copiar saídas multilinha. Use uma representação estável e simples.

Ordenação não determinística

Não compare diretamente conjuntos ou estruturas cuja ordem possa variar.

>>> sorted(obter_tags())
['api', 'python', 'teste']

Para floats, arredonde ou formate com precisão explícita. Não documente endereços de memória, timestamps atuais, UUIDs aleatórios ou caminhos temporários sem normalização.

Use __test__

O dicionário de módulo __test__ permite adicionar exemplos que não devem aparecer na ajuda principal.

__test__ = {
    "casos_extras": """
    >>> dobro(0)
    0
    """,
}

Os valores podem ser strings, funções ou classes. O finder examina docstrings dos objetos fornecidos.

Objetos examinados

testmod() procura no docstring do módulo, funções, classes, métodos e objetos encontrados em __test__. Objetos importados de outros módulos não são examinados automaticamente.

Para entender como documentação é extraída e exibida, veja pydoc no Python. Para listar funções e classes sem executar módulos, consulte pyclbr no Python.

Integre com unittest

DocTestSuite() transforma os exemplos de um módulo em uma suíte unittest.

import doctest
import unittest
import meu_modulo


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

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

DocFileSuite() faz o mesmo para arquivos textuais. Essa integração facilita descoberta, relatórios e execução junto com testes convencionais.

Prepare e limpe recursos

As suítes aceitam setUp e tearDown.

def preparar(teste):
    teste.globs["repositorio"] = RepositorioTemporario()


def limpar(teste):
    teste.globs["repositorio"].close()

suite = doctest.DocTestSuite(
    meu_modulo,
    setUp=preparar,
    tearDown=limpar,
)

Garanta limpeza mesmo quando um exemplo falha. Prefira tempfile e mocks para recursos externos.

FAIL_FAST e relatórios

A linha de comando aceita -f, equivalente a FAIL_FAST. Outras flags oferecem diff unificado, contextual ou por caracteres.

python -m doctest -v -f guia.txt

Durante desenvolvimento, falhar cedo acelera o ciclo. Em CI, executar todos os exemplos pode revelar mais regressões em uma única rodada.

Marque um exemplo como SKIP

>>> abrir_navegador()  # doctest: +SKIP

SKIP é útil quando o exemplo é puramente ilustrativo ou depende de recurso indisponível. Um número crescente de skips pode esconder documentação quebrada; revise-os regularmente.

Analise exemplos com APIs avançadas

DocTestParser extrai objetos Example de uma string.

from doctest import DocTestParser

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

DocTestFinder, DocTestRunner e OutputChecker permitem criar integrações customizadas. Use a API básica enquanto ela atender.

Segurança

O doctest executa o conteúdo encontrado. Não rode documentação recebida de usuários, pacotes desconhecidos ou repositórios não confiáveis no processo principal.

Use container ou processo isolado, usuário restrito, timeout, memória limitada, rede bloqueada e diretório temporário. Importar o módulo testado também pode executar código superior antes dos exemplos.

Erros de sintaxe e tracebacks

O guia de traceback no Python explica pilhas e formatação de exceções. Em doctest, mantenha apenas os detalhes relevantes para evitar dependência de caminhos e linhas.

Inspeção e documentação

inspect no Python ajuda ferramentas que extraem assinaturas e docstrings antes de construir suítes ou relatórios. Lembre que introspecção de objetos vivos exige importar o código.

Quando não usar doctest

  • Fluxos com muitas etapas e fixtures complexas.
  • Saídas grandes ou instáveis.
  • Testes de concorrência e tempo.
  • Integrações de rede ou banco real.
  • Propriedades com muitos casos.
  • Regras críticas que precisam de mensagens detalhadas.

Nesses casos, use unittest, pytest ou testes especializados e mantenha no doctest apenas exemplos de uso.

Boas práticas

  • Escreva exemplos curtos e determinísticos.
  • Teste comportamento público, não detalhes internos.
  • Ordene coleções antes de comparar.
  • Formate floats explicitamente.
  • Use diretivas localmente.
  • Evite elipses excessivas.
  • Integre os exemplos ao CI.
  • Isole documentação não confiável.

Conclusão

O doctest no Python mantém exemplos sincronizados com o código e transforma documentação em teste executável. Ele é excelente para APIs pequenas, tutoriais e regressões legíveis, desde que as saídas sejam estáveis.

Consulte a documentação oficial do doctest e a documentação do unittest.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Código em tela representando navegação de classes e funções com pyclbr no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pyclbr no Python: inspecione módulos

    Aprenda pyclbr no Python para listar classes, funções, métodos e definições aninhadas sem importar nem executar o módulo.

    Ler mais

    Tempo de leitura: 6 minutos
    15/08/2026
    Monitor com código binário representando instruções opcode do bytecode do Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    opcode no Python: explore o bytecode

    Aprenda opcode no Python para mapear instruções de bytecode, argumentos, saltos, caches e efeitos de pilha usando dis.

    Ler mais

    Tempo de leitura: 6 minutos
    15/08/2026
    Desenvolvedor analisando consumo de memória com tracemalloc no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    tracemalloc no Python: encontre vazamentos

    Aprenda tracemalloc no Python para comparar snapshots, encontrar crescimento de memória e diagnosticar vazamentos com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    15/08/2026
    Código com anotações de tipos representando introspecção com annotationlib no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    annotationlib no Python: leia anotações

    Aprenda annotationlib no Python 3.14 para ler anotações como valores, ForwardRef ou strings e evitar riscos de execução.

    Ler mais

    Tempo de leitura: 7 minutos
    14/08/2026
    Arquivadores organizados representando módulos importados diretamente de arquivos ZIP com zipimport no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    zipimport no Python: importe de ZIPs

    Aprenda zipimport no Python para importar módulos e pacotes de arquivos ZIP, trabalhar com loaders e evitar riscos de segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    14/08/2026
    Diagrama de diretórios representando caminhos site-packages e configuração do módulo site no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    site no Python: entenda os caminhos

    Aprenda o módulo site no Python para entender site-packages, user site, arquivos .pth, sitecustomize, usercustomize e opções de inicialização.

    Ler mais

    Tempo de leitura: 8 minutos
    14/08/2026