为什么导入模块会破坏我的doctest(Python 2.7)

吉姆·德拉汉

我尝试在Python 2.7程序的类StringIO中的doctest使用实例我没有从测试中获得任何输出,而是得到了一个响应,“什么也没有”。

这个简化的测试案例展示了该错误:

#!/usr/bin/env python2.7
# encoding: utf-8

class Dummy(object):
    '''Dummy: demonstrates a doctest problem

    >>> from StringIO import StringIO
    ... s = StringIO()
    ... print("s is created")
    s is created
    '''

if __name__ == "__main__":
    import doctest
    doctest.testmod()

预期的行为:通过测试。

观察到的行为:测试失败,输出如下:

% ./src/doctest_fail.py
**********************************************************************
File "./src/doctest_fail.py", line 7, in __main__.Dummy
Failed example:
    from StringIO import StringIO
    s = StringIO()
    print("s is created")
Expected:
    s is created
Got nothing
**********************************************************************
1 items had failures:
   1 of   1 in __main__.Dummy
***Test Failed*** 1 failures.

为什么此doctest失败?为了能够在我的doctest中使用类似StringIO的功能(具有文件接口的文字字符串),我需要进行哪些更改?

吉姆·德拉汉

[以wim的正确答案为基础,但通过查看底层doctest语义来解释其中的原因。]

该示例失败,因为它在单独的简单语句之前使用PS2语法(...)而不是PS1语法(>>>)。

更改...>>>

#!/usr/bin/env python2.7
# encoding: utf-8

class Dummy(object):
    '''Dummy: demonstrates a doctest problem

    >>> from StringIO import StringIO
    >>> s = StringIO()
    >>> print("s is created")
    s is created
    '''

if __name__ == "__main__":
    import doctest
    doctest.testmod()

现在,更正后的示例已重命名为doctest_pass.py,可以正确运行。它不产生输出,意味着所有测试都通过:

% src/doctest_pass.py                       

为什么>>>语法正确?适用于doctest的Python库参考25.2.3.2。Docstring示例如何识别?应该是找到答案的地方,但是对于这种语法尚不十分清楚。

Doctest扫描文档字符串,查找“示例”。在它看到PS1字符串的地方>>>,以从那里到该行结尾的所有内容为例。它还将以PS2字符串开头的以下任何行附加...到示例(请参阅:_EXAMPLE_RE在类中doctest.DocTestParser,行584-595)。它将后续的行,直到下一个空行或以PS1字符串开头的行作为通缉输出。

文档测试编译每个实施例为Python“互动语句”,使用compile()内置函数在exec声明(参见:doctest.DocTestRunner.__run(),线1314至1315年)。

交互式语句”是以换行符或“复合语句”结尾的语句列表复合语句,例如ifortry语句,“一般来说,[…跨越]多行,尽管在简单的形式中,整个复合语句可以包含在一行中。” 这是多行复合语句:

if 1 > 0:
    print("As expected")
else:
    print("Should not happen")

语句列表是一行中的一个或多个简单语句,以分号分隔。

from StringIO import StringIO
s = StringIO(); print("s is created")

因此,问题的doctest失败了,因为它包含一个包含三个简单语句的示例,并且没有分号分隔符。将PS2字符串更改为PS1字符串成功,因为它将文档字符串转换为三个示例的序列,每个示例都有一个简单的语句。尽管这三行代码可以一起对一项功能进行测试,但它们并不是单个测试夹具。它们是三个测试,其中两个设置状态,但并未真正测试主要功能。

顺便说一句,您可以看到doctest使用-v标志识别的示例数请注意,它说:“ 3 tests in __main__.Dummy”。人们可能会将三行视为一个测试单元,但会doctest看到三个示例。前两个示例没有预期的输出。当示例执行且不生成任何输出时,将被视为“通过”。

% src/doctest_pass.py -v
Trying:
    from StringIO import StringIO
Expecting nothing
ok
Trying:
    s = StringIO()
Expecting nothing
ok
Trying:
    print("s is created")
Expecting:
    s is created
ok
1 items had no tests:
    __main__
1 items passed all tests:
   3 tests in __main__.Dummy
3 tests in 2 items.
3 passed and 0 failed.
Test passed.

在单个文档字符串中,示例按顺序执行。每个示例的状态更改将在同一文档字符串中保留以下示例的状态。因此,该import语句定义模块名称,s =赋值语句使用该模块名称并定义变量名称,依此类推。doctest文档,25.2.3.3。什么是执行上下文?,当说“示例可以自由使用…在运行的文档字符串中更早定义的名称”时,倾斜地公开了这一点。

该节中的前面的句子是:“每次doctest都找到一个要测试的文档字符串,它使用M的全局变量的浅表副本,因此…M中的一个测试不能留下偶然允许另一个测试起作用的碎屑”。有点误导。的确,M中的一个测试不会影响其他文档字符串中的测试但是,在单个文档字符串中,较早的测试肯定会留下碎屑,这很可能会影响以后的测试。

为什么在Python库参考中的doctest 25.2.3.2。Docstring示例如何识别?,显示...语法示例该示例显示一条if语句,它是多行上的复合语句。第二行和后续行用PS2字符串标记。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在go lang中,为什么是7?断言(5 ^ 2 == 7)

Java:为什么7 / -3是-2?

为什么导入节点模块会破坏我的内部Typescript名称空间在atom-typescript中?

当Windows 7似乎免费提供2GB以上的内存时,为什么Windows 7会说我的内存不足?

在Redhat 7上运行的.bashrc中添加anaconda路径会破坏x2go登录

为什么“ 2 + x = 7”有效的Haskell?

为什么php 016除以2回答7?

为什么延迟加载的模块必须导入commonModule?角度2

为什么n = [1,2,3,4,5,6,7,8],n [:6:-2]在Python中是[8]?

为什么在v2没有实现缩放时d3.js v3会破坏我的力图?

为什么 int arr[]={0,3,2,4,5,6,7}; 给出错误和 int arr[7]={0,3,2,4,5,6,7}; 不是

为什么-O2或更高的clang优化会破坏此代码?

RHEL7:如何解决“导入读取失败(2)”?

angular7 中 2 个模块的声明错误

Xcode 7 beta 2上的“没有这样的模块”

Angular2 RC7 Http模块错误加载

VDSO(7) 和 SYSCALL(2) 之间有什么关系?

什么是Delphi XE7中的“ HotfixLevel 2”?

char c [2] = {[1] = 7}是什么?做?

为什么操作2 ** 2 ** 2 ** 2 ** 2 ** 2会导致python挂掉?

为什么我会进入日期到达博物馆 +7 小时?

为什么我会从iText7 C#中提取重复的页面?

iOS7-当我将内容查看为iOS 6或7时,为什么页面的元素会移动

sudo apt-get upgrade 会破坏我的python 2环境吗?

如何在Windows 7中运行python 2和3?

如何在Windows 7中运行python 2和3?

Think Python 2nd Edition 练习 7-1

为什么我得到 7 作为输出?

为什么在JavaScript中[5,6,8,7] [1,2] = 8?