【问题标题】:How to test nested/re-raised exceptions with doctest?如何使用 doctest 测试嵌套/重新引发的异常?
【发布时间】:2018-11-11 23:42:35
【问题描述】:

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

#!/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

【问题讨论】:

    标签: python python-3.x exception doctest


    【解决方案1】:

    问题在于 doctest 在内部是如何工作的。基本上它在同一个 python 解释器中加载、编译和评估 python 的 sn-ps。

    这与 python 加载和执行给定代码的方式不同。

    这是发挥神奇作用的 doctest 的 sn-p:

    # 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

    回溯标头后跟一个可选的回溯堆栈,其 doctest 忽略内容。回溯堆栈通常是 从交互式会话中省略或逐字复制。

    现在,最后一部分似乎仅适用于单个例外; “多重或嵌套异常”不是这样工作的,您可能无法检查它们的回溯。看到这个thread

    如果你仍然想检查这个,你可以使用另一个“doctest 引擎”,比如byexample。它有一个compatibility mode with doctest,所以你不需要重写所有东西。

    免责声明:我是byexample 的作者。正如我在thread 中解释的那样,我是 doctests 的忠实粉丝,但它有其局限性。我希望byexample 可以填补空白并对其他人有用。

    【讨论】:

      猜你喜欢
      • 2013-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-27
      • 2019-07-22
      相关资源
      最近更新 更多