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 * 2O 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 -vEm 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.pyPara 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 / bQuando 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: +ELLIPSISUma 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>
terceiraEssa 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.txtDurante 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: +SKIPSKIP é ú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.







