如何使我的(Python 2.7)代码知道它是否在doctest中运行?
场景如下:我有一个函数,该函数将print()一些输出作为参数传递给文件描述符,如下所示:
from __future__ import print_function
def printing_func(inarg, file=sys.stdout):
# (do some stuff...)
print(result, file=file)
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试printing_func()在doctest中使用时,测试失败;由于我file在调用时指定了关键字参数print(),因此输出实际上到达sys.stdout了doctest模块设置的默认输出重定向,而不是doctest设置的任何默认输出重定向,并且doctest从不看到输出。
因此,如何printing_func()知道它是否在doctest中运行,以便它知道file在调用时不传递关键字参数print()?
Niten 的版本inside_doctest似乎过于宽泛。无论是sys.stdout用于日志记录还是在 doctest 之外的框架中进行测试时,重新定义 并不罕见,因此它会给出误报。
更窄的测试如下所示:
import sys
def in_doctest():
"""
Determined by observation
"""
if '_pytest.doctest' in sys.modules:
return True
##
if hasattr(sys.modules['__main__'], '_SpoofOut'):
return True
##
if sys.modules['__main__'].__dict__.get('__file__', '').endswith('/pytest'):
return True
##
return False
def test():
"""
>>> print 'inside comments, running in doctest?', in_doctest()
inside comments, running in doctest? True
"""
print 'outside comments, running in doctest?', in_doctest()
if __name__ == '__main__':
test()
Run Code Online (Sandbox Code Playgroud)
in_doctestdoctest 类的测试_SpoofOut用于替换sys.stdout. doctest 模块的其他属性可以通过相同的方式进行验证。并不是说您可以阻止另一个模块重用某个名称,但这个名称并不常见,因此可能是一个不错的测试。
将以上内容放入test.py中。在非文档测试模式下运行它,python test.py会产生:
outside comments, running in doctest? False
Run Code Online (Sandbox Code Playgroud)
在 doctest 详细模式下运行,python -m doctest test.py -v会产生:
Trying:
print 'inside comments, running in doctest?', in_doctest()
Expecting:
inside comments, running in doctest? True
ok
Run Code Online (Sandbox Code Playgroud)
我同意其他人的评论,即让代码了解 doctest 通常是一个坏主意。我只在某种特殊的情况下才这样做——当我需要通过代码生成器创建测试用例时,因为有太多的测试用例无法有效地手动制作。但如果你需要这样做,上面的内容就是一个不错的测试。
读完后我找到了答案doctest.py;在这里发帖供后代使用...
Doctest 通过将新的文件描述符分配给sys.stdout. sys.stdout问题是我的函数描述在 doctest 重新定义之前关闭了原始文件描述符的值。
相反,如果我执行以下操作:
def printing_func(inarg, file=None):
# (do some stuff...)
if file is None:
file = sys.stdout
print(result, file=file)
Run Code Online (Sandbox Code Playgroud)
thenprinting_func()将捕获sys模块而不是,并且当它运行时,它将从if 运行在测试中sys.stdout检索 doctest 的重新定义的stdout属性。sys
编辑:这也提供了一种简单的方法来检查我们是否在文档测试中运行:
def inside_doctest(original_stdout=sys.stdout):
return original_stdout != sys.stdout
Run Code Online (Sandbox Code Playgroud)