下面的玩具脚本说明了这个问题:
#!/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()
,我会得到文档字符串指定的输出:
% 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
最佳答案
问题在于 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 引擎的部分堆栈框架,使其与您的预期不同。
The traceback header is followed by an optional traceback stack, whose contents are ignored by doctest. The traceback stack is typically omitted, or copied verbatim from an interactive session.
现在,最后一部分似乎仅适用于单个异常(exception); “多重或嵌套异常”不是那样工作的,您可能无法检查它们的回溯。看这个thread .
如果你仍然想检查这个,你可以使用另一个“doctest 引擎”,比如 byexample .它有一个 compatibility mode with doctest因此您不需要重写所有内容。
免责声明:我是 byexample 的作者.正如我在此 thread 中解释的那样我非常喜欢 doctests,但它有其局限性。我希望 byexample可以填补空白并对其他人有用。
关于python - 如何使用 doctest 测试嵌套/重新引发的异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53254374/