有没有办法只执行文档测试,而忽略打印函数调用?
Is there way to only perform the doctests, ignoring print function calls?
假设地说,我的函数 returns 一个值 和 有很多打印语句 (可能有 100 个或更多)。
有没有办法运行 doctest
使得所有其他打印工作都可以ignored/skipped(我熟悉+SKIP
指令,这是为了跳过 doctest
示例),即当我使用 doctest
s:
执行我的函数(或 运行 我的模块作为脚本)时
python mymodule.py
或者:
python -m doctest mymodule.py
我应该得到:
- 没什么,万一成功了;或
- 任何测试示例失败时的错误消息;
仅此而已。 运行 doctest
不应该给我一个终端 window 充满那些 print
函数调用的输出/文本。
请不要建议使用单元测试(例如 unittest
),因为它会扼杀问题的本质。
doctest
使用 stdout
、 而不是 stderr
来显示任何失败测试的消息。因此,您不能像最初建议的那样修补 stdout
- 这将抑制您的 print
调用 和 来自 doctest
.[=26= 的任何消息]
一个选项是定义 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')
这也需要更改函数定义,但至少可以避免更改这些函数的 bodies。
第三个选项是为整个被测模块修补 print
,例如:
def baz():
"""Does whatever.
>>> baz()
"""
print('Hello world')
if __name__ == '__main__':
import doctest
print = lambda *args, **kwargs: None
doctest.testmod()
请注意,这也会影响 doctest
看到的输出,因此您不要在文档字符串中包含任何 print
输出(我认为这是个好消息!)它赢了不过,请使用 python -m doctest mymodule.py
。
除了 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
:
假设地说,我的函数 returns 一个值 和 有很多打印语句 (可能有 100 个或更多)。
有没有办法运行 doctest
使得所有其他打印工作都可以ignored/skipped(我熟悉+SKIP
指令,这是为了跳过 doctest
示例),即当我使用 doctest
s:
python mymodule.py
或者:
python -m doctest mymodule.py
我应该得到:
- 没什么,万一成功了;或
- 任何测试示例失败时的错误消息;
仅此而已。 运行 doctest
不应该给我一个终端 window 充满那些 print
函数调用的输出/文本。
请不要建议使用单元测试(例如 unittest
),因为它会扼杀问题的本质。
doctest
使用 stdout
、 而不是 stderr
来显示任何失败测试的消息。因此,您不能像最初建议的那样修补 stdout
- 这将抑制您的 print
调用 和 来自 doctest
.[=26= 的任何消息]
一个选项是定义 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')
这也需要更改函数定义,但至少可以避免更改这些函数的 bodies。
第三个选项是为整个被测模块修补 print
,例如:
def baz():
"""Does whatever.
>>> baz()
"""
print('Hello world')
if __name__ == '__main__':
import doctest
print = lambda *args, **kwargs: None
doctest.testmod()
请注意,这也会影响 doctest
看到的输出,因此您不要在文档字符串中包含任何 print
输出(我认为这是个好消息!)它赢了不过,请使用 python -m doctest mymodule.py
。
除了 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
: