有没有办法只执行doctests,忽略打印函数调用?

时间:2015-04-17 10:39:12

标签: python python-3.x testing doctest

假设,我的函数返回一个值有很多打印语句(可能是100或更多)。

有没有办法运行doctest,以便可以忽略/跳过所有其他打印工作(我熟悉+SKIP指令,用于跳过doctest示例) ,即当我用doctest s执行我的函数(或以脚本运行我的模块)时:

python mymodule.py

或者:

python -m doctest mymodule.py

我应该得到:

  • 没有,如果成功;或
  • 如果任何测试示例失败,则会出现错误消息;

,没有别的。运行doctest不应该给我一个充满来自print函数调用的输出/文本的终端窗口。

请不要建议使用单元测试(例如unittest)因为它会杀死问题的本质。

2 个答案:

答案 0 :(得分:5)

doctest使用stdout stderr来显示来自任何失败测试的消息。因此,您无法根据最初建议的答案修补stdout - 这将取消print来自doctest的{​​{1}}来电来自<{1}}的消息。


一个选项是定义print带有额外verbose参数的函数,以便您可以在必要时对其进行抑制。

def foo(verbose=True):
    """Does whatever.

        >>> foo(verbose=False)

    """
    if verbose:
        print('Hello world')

虽然您必须更改这些功能,但在不测试时也会为您提供有用的选项。


另一个是明确地向使用它的函数提供适当的print函数,允许你在运行时传递NOOP:

def bar(print=print):
    """Does whatever.

        >>> bar(print=lambda *args, **kwargs: None)

    """
    print('Hello world')

这也需要更改函数定义,但至少要避免更改这些函数的主体


第三种选择是为整个被测模块打出print,例如:

def baz():
    """Does whatever.

        >>> baz()

    """
    print('Hello world')

if __name__ == '__main__':

    import doctest

    print = lambda *args, **kwargs: None

    doctest.testmod()

请注意,这会影响doctest看到的输出,因此您不会在docstring中包含任何print输出(我认为这是个好消息!)它赢了&但是,不能使用python -m doctest mymodule.py

答案 1 :(得分:1)

除了jonrsharpe的优秀答案之外,还有一种方法,即 使用python3 -m doctest module.py构造。

#!/usr/bin/python3 -OO
'''
Some ideas for adding additional verbosity during doctest, and for
reducing verbosity and startup delays during doctest or pydoc.
'''
from __future__ import print_function  # for compatibility with python2
import sys, os, logging
logging.basicConfig(level = logging.DEBUG if __debug__ else logging.INFO)
COMMAND = os.path.splitext(os.path.basename(sys.argv[0]))[0]
if COMMAND in ['doctest', 'pydoc']:
    NONDOCTESTPRINT = lambda *args, **kwargs: None
    DOCTESTDEBUG = logging.debug
else:
    NONDOCTESTPRINT = print
    DOCTESTDEBUG = lambda *args, **kwargs: None
    # You can also use this `else` block to import things not needed during
    # doctest, especially slow-loading modules like `requests`,
    # or to do some other verbose or slow initialization.

def test(string):
    '''
    print string after lead-in

    >>> test("I'm in love with you!")
    Listen!
    I'm in love with you!
    '''
    DOCTESTDEBUG("If this works, you shouldn't see anything but this")
    print('Listen!')
    NONDOCTESTPRINT('Do you want to know a secret?')
    NONDOCTESTPRINT('Do you promise not to tell? Whoa, oh...')
    NONDOCTESTPRINT('Closer...')
    NONDOCTESTPRINT('Let me whisper in your ear...')
    NONDOCTESTPRINT('Say the words you long to hear...')
    print(string)

if __name__ == '__main__':
    test(' '.join(sys.argv[1:]) or 'Taxation is theft.')

以下是输出的内容,具体取决于它的调用方式。

jcomeau@aspire:/tmp$ python3 -m doctest doctesttest.py 
DEBUG:root:If this works, you shouldn't see anything but this
jcomeau@aspire:/tmp$ python3 doctesttest.py This is a test!
Listen!
Do you want to know a secret?
Do you promise not to tell? Whoa, oh...
Closer...
Let me whisper in your ear...
Say the words you long to hear...
This is a test!

pydoc doctesttest

pydoc output of above script