使用冻结异常时,单元测试中出现意外的“FrozenInstanceError”

问题描述 投票:0回答:1

我有一个单元测试,我想将其失败显示为错误报告的一部分。重要的是,不仅测试因错误而失败,而且错误消息非常清楚地证明了潜在的错误。我确实希望测试通过。

这是一个最小的例子:

import unittest

import attrs


@attrs.frozen
class FrozenException(Exception):
    pass


class BugException(Exception):
    pass


class Test(unittest.TestCase):

    def testFromNone(self):
        raise BugException

    def testFromFrozen(self):
        try:
            raise FrozenException
        except FrozenException:
            raise BugException


if __name__ == '__main__':
    unittest.main()

当我执行此文件时,我期望(并且希望)两种测试方法都会失败并显示

BugException
作为失败的原因。
testFromNone
表现如预期:

$ python3 -m unittest scratch.Test.testFromNone
E
======================================================================
ERROR: testFromNone (scratch.Test.testFromNone)
----------------------------------------------------------------------
Traceback (most recent call last):
...
scratch.BugException

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)

但是,运行

testFromFrozen
会导致单元测试代码本身崩溃1,将
BugException
隐藏在堆栈跟踪深处2:

$ python3 -m unittest scratch.Test.testFromFrozen
Traceback (most recent call last):
...
<very long traceback>
...
attr.exceptions.FrozenInstanceError

看起来

unittest
框架对测试未捕获的异常进行了某种后处理,并且在此处理过程中,它尝试改变存储在
FrozenException 中的 
BugException
 实例
的回溯,触发
FrozenInstanceError

如何解决此问题以便测试显示正确的错误消息?如果可能的话,我宁愿避免删除

@attrs.frozen
装饰器3

Python 版本 3.11.8,

attrs
版本 22.2.0。


1仅当未在测试方法体内捕获异常时才能观察到此行为。如果我的示例更改为使用

assertRaises
或显式
try/catch
,则不会引发
FrozenInstanceError


2在现实世界中,超出了本示例的范围,症状甚至更糟,因为意外错误导致整个测试套件挂起,导致无法执行进一步的测试,并且进程只是坐在那里,直到测试作业超时。


3在真实的代码中,冻结的异常类其实是有属性的。

python exception immutability python-unittest python-attrs
1个回答
0
投票

您在 attrs 23.1.0 及更高版本中获得预期结果:

EE
======================================================================
ERROR: testFromFrozen (__main__.Test.testFromFrozen)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/hynek/FOSS/attrs/t2.py", line 22, in testFromFrozen
    raise FrozenException
FrozenException

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/hynek/FOSS/attrs/t2.py", line 24, in testFromFrozen
    raise BugException
BugException

======================================================================
ERROR: testFromNone (__main__.Test.testFromNone)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/hynek/FOSS/attrs/t2.py", line 18, in testFromNone
    raise BugException
BugException

----------------------------------------------------------------------
Ran 2 tests in 0.000s

FAILED (errors=2)

相关更改在https://github.com/python-attrs/attrs/pull/1081并允许修改

__traceback__

© www.soinside.com 2019 - 2024. All rights reserved.