如何使用doctest测试嵌套/重新引发的异常?

3
以下玩具脚本说明了问题:
#!/usr/bin/env python3

def bomb():
    """
    >>> bomb()
    Traceback (most recent call last):
      File "<string>", line 18, in bomb
    ZeroDivisionError: division by zero
    <BLANKLINE>
    During handling of the above exception, another exception occurred:
    <BLANKLINE>
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<string>", line 20, in bomb
    Exception: re-raised
    """
    try:
        1/0
    except Exception as exception:
        raise Exception('re-raised')

if __name__ == '__main__' and '__file__' in globals():
    import sys
    if len(sys.argv) > 1 and sys.argv[1] == '-t':
        import doctest
        doctest.testmod()
    else:
        bomb()

如果我在Python解释器中执行bomb(),我将获得docstring指定的输出:
% python3
Python 3.5.1 (default, May 24 2016, 20:04:39)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exec(open('demo.py').read())
>>> bomb()
Traceback (most recent call last):
  File "<string>", line 18, in bomb
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 20, in bomb
Exception: re-raised
>>>

doctest 然而错误地报告了一个失败:

**********************************************************************
File "./demo.py", line 5, in __main__.bomb
Failed example:
    bomb()
Expected:
    Traceback (most recent call last):
      File "<string>", line 16, in bomb
    ZeroDivisionError: division by zero
    <BLANKLINE>
    During handling of the above exception, another exception occurred:
    <BLANKLINE>
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<string>", line 18, in bomb
    Exception: re-raised
Got:
    Traceback (most recent call last):
      File "./demo.py", line 18, in bomb
        1/0
    ZeroDivisionError: division by zero
    <BLANKLINE>
    During handling of the above exception, another exception occurred:
    <BLANKLINE>
    Traceback (most recent call last):
      File "/usr/lib/python3.5/doctest.py", line 1320, in __run
        compileflags, 1), test.globs)
      File "<doctest __main__.bomb[0]>", line 1, in <module>
        bomb()
      File "./demo.py", line 20, in bomb
1个回答

3
问题在于doctest的内部工作方式。基本上,它在同一个Python解释器中加载、编译和评估Python代码片段。
这与Python加载和执行给定代码的方式不同。
以下是实现魔术的doctest代码片段:
# Don't blink!  This is where the user's code gets run.
exec(compile(example.source, filename, "single",
     compileflags, 1), test.globs)

当执行的代码引发异常时,回溯包含 doctest 引擎的部分堆栈帧,使其与您期望的不同。
来自 doctest 文档
引导头后面是一个可选的 traceback 堆栈,其内容被 doctest 忽略。traceback 堆栈通常会被省略或从交互式会话中逐字复制。
现在,最后一部分似乎仅适用于单个异常;“多个或嵌套异常”不像那样工作,并且您可能无法检查它们的回溯。请参见此 线程
如果您仍想检查此问题,可以使用另一个 "doctest 引擎",例如 byexample。它具有与 doctest 的 兼容模式,因此您不需要重写所有内容。 < p >< em > 免责声明: 我是byexample的作者。正如我在这个thread中所解释的那样,我非常喜欢doctest,但它也有其局限性。我希望byexample可以填补这个空白,并对其他人有用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接