python - unittest.assertRaisesRegex 被称为上下文管理器时的不同错误消息
问题描述
上下文(可以跳过,真正的问题在后面)
整件事并不重要,但我正在进行一项让我越来越困惑的调查。
我的一个宠物项目有一些依赖 Python 异常消息(而不仅仅是类型)的逻辑。由于它非常脆弱,我确保我可以在 Travis 上运行大多数 Python 版本的东西。
最近,我意识到这段代码set.add(0)
导致了一个异常,其消息应该是这样的:
描述符“add”需要一个“set”对象但收到一个“int”
然而,在 Python 3.7+ 的某些版本中,在一些测试用例中情况开始有所不同。显然消息更像是:
“‘set’对象的描述符‘add’不适用于‘int’对象”
仅仅因为我想确定这是 Python 开发人员的意图,我想找到确切的提交来改变它,git bisect
并开始寻找一种简单的方法来重现这个问题。不幸的是,我无法在本地重现这种行为,一件事导致另一件事我掉进了兔子洞,以许多谜团结束,其中一个涉及unittest.assertRaisesRegex
.
意外unittest.assertRaisesRegex
行为
我编写了以下测试,这些测试看起来与文档中的示例惊人地相似unittest.assertRaisesRegex
——一个测试提供可调用和相应的参数,另一个测试依赖于上下文管理器:
DESCRIPT_REQUIRES_TYPE_RE = r"descriptor '\w+' requires a 'set' object but received a 'int'"
...
def test_assertRaisesRegex(self):
self.assertRaisesRegex(TypeError, DESCRIPT_REQUIRES_TYPE_RE, set.add, 0)
def test_assertRaisesRegex_contextman(self):
with self.assertRaisesRegex(TypeError, DESCRIPT_REQUIRES_TYPE_RE):
set.add(0)
我希望他们两个都有完全相同的行为,但他们没有。
(版本号用python -VV
和检索python -c "import sys; print(sys._git)"
)
在某些版本上,两个测试都通过:
- Python 3.6 及之前版本
- Python 3.7.0a4+ (heads/master:4666ec5, Jan 26 2018, 04:14:24) - [GCC 4.8.4] - ('CPython', 'heads/master', '4666ec5'))
在某些版本上,两个测试都失败了:
- Python 3.8.0a1+ (heads/master:8a03ff2, Feb 9 2019, 07:30:26) [GCC 5.4.0 20160609] - ('CPython', 'heads/master', '8a03ff2')
在某些版本上,只会
test_assertRaisesRegex_contextman
失败,这让我感到困惑:- Python 3.7.1(默认,2018 年 12 月 5 日,18:09:53)[GCC 5.4.0 20160609] - ('CPython', '', '')
- Python 3.7.2+(heads/3.7:3fcfef3,2019 年 2 月 9 日,07:30:09)[GCC 5.4.0 20160609] -('CPython','heads/3.7','3fcfef3')
当它们发生时,故障如下所示:
======================================================================
FAIL: test_assertRaisesRegex (didyoumean_sugg_tests.SetAddIntRegexpTests)
----------------------------------------------------------------------
TypeError: descriptor 'add' for 'set' objects doesn't apply to 'int' object
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/travis/build/.../didyoumean_sugg_tests.py", line 19, in test_assertRaisesRegex
self.assertRaisesRegex(TypeError, DESCRIPT_REQUIRES_TYPE_RE, set.add, 0)
AssertionError: "descriptor '\w+' requires a 'set' object but received a 'int'" does not match "descriptor 'add' for 'set' objects doesn't apply to 'int' object"
和
======================================================================
FAIL: test_assertRaisesRegex_contextman (didyoumean_sugg_tests.SetAddIntRegexpTests)
----------------------------------------------------------------------
TypeError: descriptor 'add' for 'set' objects doesn't apply to 'int' object
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/travis/build/.../didyoumean/didyoumean_sugg_tests.py", line 23, in test_assertRaisesRegex_contextman
set.add(0)
AssertionError: "descriptor '\w+' requires a 'set' object but received a 'int'" does not match "descriptor 'add' for 'set' objects doesn't apply to 'int' object"
为什么这两个外观相似的测试会有不同的行为?
让我感到困惑的其他要点
我无法在我要签出和构建的 cpython 代码上本地重现该问题(即使使用正确的 SHA1)
在 Travis 上,运行
python -c "set.add(0)"
总是会导致相同的(预期的)字符串:
TypeError: descriptor 'add' requires a 'set' object but received a 'int'
目前状态
一切都可能归结为我缺少的一个简单细节,但我现在一无所知。欢迎任何建议。如果需要更多数据,我很乐意触发更多 Travis 构建。
解决方案
推荐阅读
- angular - 如何使用 NgBootstrap 在 Angular 中显示多个下拉菜单
- c# - .Net 核心单元测试错误 - 源 IQueryable 未实现 IAsyncEnumerable<...>
- string - 我如何制作具有许多输入的整数列表?
- xslt - 无法在 XSL 中找到用户定义函数的源代码
- javascript - 从 HTML 获取数据到 Node.js
- google-cloud-platform - 为 Google Cloud 产品创建 .display 文件的文档
- cplex - 关于 CPLEX 文件
- scala - 从scala中的弹性搜索中检索数据/值
- python - 如何添加到函数内部的变量?
- regex - 检查字符串是否与 Unix 中的正则表达式匹配