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

标签 python python-3.x exception doctest

下面的玩具脚本说明了这个问题:

#!/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 引擎的部分堆栈框架,使其与您的预期不同。

来自doctest documentation :

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/

相关文章:

c++ - 异常(exception):设备为nullptr。 D3D11中的读取访问冲突

c# - 找不到 OWIN HttpListener

python - 将微秒转换为人类可读的时间

python - PyMC3 & Theano - Theano 代码在导入 pymc3 后停止工作

python - 正则表达式避免不必要的组

python elasticsearch使用传输客户端

python - PyQt:从 QListWidget 中删除自定义小部件

python - 为什么 Python 套接字在 HTTP 套接字的 recv 循环期间没有收到最终的空白值?

python-3.x - Docker 和 Plotly

java - Servlet 中的意外异常行为