Pode python doctest ignorar algumas linhas de saída?
Pergunta
Eu gostaria de escrever uma doctest assim:
"""
>>> print a.string()
foo : a
bar : b
date : <I don't care about the date output>
baz : c
"""
Existe alguma maneira de fazer isso? Acho que faria mais sentido para mudar para unittest, mas estou curioso para saber se é possível especificar um intervalo de saída que não deve ser combinado para o teste em doctest.
Obrigado!
Solução
Com doctest.ELLIPSIS
, você pode usar ...
para significar "coincidir com qualquer seqüência aqui". Você pode definir opções doctest
com uma directiva doctest, para ativá-la para o caso de apenas um teste: um exemplo no documentos online é:
>>> print range(20) # doctest:+ELLIPSIS
[0, 1, ..., 18, 19]
Se você quiser uma opção doctest a ser ativo durante toda, você pode passá-lo como argumento optionflags=
para o que quer que doctest funções que utiliza, por exemplo, doctest.testfile
. (Você pode passar vários sinalizadores de opção lá usando o operador |
para bit-ou-los).
Outras dicas
Respondendo a perguntas sobre "como podemos ignorar toda a linha": sim, o fato de que "..." também se parece com uma continuação como o torna difícil de ignorar a saída inteira. Você pode usar "#doctest: + SKIP" se você só quer pular o exemplo inteiramente, mas isso não vai funcionar se você está confiando em seus efeitos colaterais. Se você realmente necessidade de fazer isso, eu suponho que você poderia macaco-patch do próprio módulo doctest, embora eu não especialmente recomendar-lo:
>>> import doctest
>>> doctest.ELLIPSIS_MARKER = '-etc-'
>>> print 12 # doctest: +ELLIPSIS
-etc-
(passar este teste.)
Ou você poderia stdout e / ou stderr temporariamente suprimir:
>>> # Suppress stdout
>>> import sys
>>> class DevNull:
... def noop(*args, **kwargs): pass
... close = write = flush = writelines = noop
>>> sys.stdout = DevNull()
>>> # Run a test and ignore output (but we need its side effects)
>>> print 12 # NOTE: stdout is suppressed!
>>> # Restore stdout
>>> sys.stdout = sys.__stdout__
(este teste também passa.)
Ignorando toda a linha é pouco embora complicado. Aqui:
"""
>>> do_your_thing() #doctest:+ELLIPSIS
...
"""
O ponto triplo será interpretado como linha de continuação, e causar um erro de sintaxe.
Se você quiser ignorar toda a linha, você precisa de algo como:
"""
>>> sys.stdout.write('skip from here '); do_your_thing() #doctest:+ELLIPSIS
skip from here ...
"""
Eu achei mais fácil de simplesmente atribuir os valores de retorno desnecessários a uma variável:
>>> _ = do_something()
>>> check_something()
True
Você pode escrever tuplas antes e depois da sua função (corte inspirado pela resposta de Mark Horvath):
def foo():
"""
>>> ();foo();() # doctest: +ELLIPSIS
(...)
"""
print "Hello world"
return "Hello world"
posso ter reticências no início da linha em um Python doctest? explica como criar um verificador de saída personalizado que utiliza uma cadeia adicional, como uma elipse. Isso iria deixá-lo escrever o seguinte, enquanto ainda usado '...' em outro lugar.
def foo():
"""
>>> foo() # doctest: +ELLIPSIS
[...] world
"""
print "hello world"