如何确定代码是否在doctest中运行?

时间:2011-11-14 00:49:32

标签: python doctest

如何让我的(Python 2.7)代码知道它是否在doctest中运行?

场景如下:我有一个函数print()输出到作为参数传入的文件描述符,如下所示:

from __future__ import print_function

def printing_func(inarg, file=sys.stdout):
    # (do some stuff...)
    print(result, file=file)

但是当我尝试在doctest中使用printing_func()时,测试失败了;因为我在调用file时指定了关键字参数print(),所以输出实际上转到sys.stdout而不是doctest模块设置的默认输出重定向,而doctest从未看到输出

那么如何让printing_func()知道它是否在doctest中运行,以便它在调用file时知道不传递print()关键字参数?

4 个答案:

答案 0 :(得分:3)

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()
in_doctest类doctest的

_SpoofOut次测试用于替换sys.stdout。 doctest模块的其他属性可以通过相同的方式进行验证。并不是说你可以阻止另一个模块重用一个名字,但这个名字并不常见,所以可能是一个不错的测试。

将上述内容放在test.py中。在非doctest模式下运行python test.py会产生:

outside comments, running in doctest? False

以doctest verbose模式运行,python -m doctest test.py -v产生:

Trying:
    print 'inside comments, running in doctest?', in_doctest()
Expecting:
    inside comments, running in doctest? True
ok

我同意其他人的意见,即使代码知道doctest通常是一个坏主意。我只是在异国情调的情况下完成它 - 当我需要通过代码生成器创建测试用例时,因为有太多人无法手动制作。但如果你需要这样做,以上是一个不错的测试。

答案 1 :(得分:1)

我在阅读doctest.py之后想出了答案;在这里张贴后代...

Doctest通过为sys.stdout分配新的文件描述符来重定向标准输出。问题是我的函数描述在doctest重新定义之前关闭了原始sys.stdout文件描述符的值。

相反,如果我执行以下操作:

def printing_func(inarg, file=None):
    # (do some stuff...)

    if file is None:
        file = sys.stdout

    print(result, file=file)

然后printing_func()将捕获sys模块而非sys.stdout,当它运行时,如果在stdout内部运行,它将从sys检索doctest的重新定义的def inside_doctest(original_stdout=sys.stdout): return original_stdout != sys.stdout 属性测试。

编辑:这也可以让您轻松检查我们是否在doctest中运行:

{{1}}

答案 2 :(得分:0)

FWIW(很抱歉迟到和多余)许多开发人员将“if test”视为反模式。

即。如果你测试的代码在测试时做的不同于“真实”运行,你会遇到麻烦。即使你相信你这样做是有充分理由的。因此,上面的评论称赞你的解决方案没有那样做。当我试图使用“if test”模式时,我会尝试重构事物,因此不需要它。

答案 3 :(得分:0)

我只是检查模块'doctest'是否已加载。

def in_doctest():
    import sys
    return 'doctest' in sys.modules