我有一个单元测试,我想将其失败显示为错误报告的一部分。重要的是,不仅测试因错误而失败,而且错误消息非常清楚地证明了潜在的错误。我确实不希望测试通过。
这是一个最小的例子:
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在真实的代码中,冻结的异常类其实是有属性的。
您在 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__
。