有没有办法比较unittest
中的嵌套数据结构,但忽略具体类型的对象,如assertSequenceEqual
但递归,例如:
#!/usr/bin/env python
import unittest
class DeepCompareTestCase(unittest.TestCase):
def test_compare(self):
# this test fails
self.assertSequenceEqual(
[['abc', 'def']],
(('abc', 'def'),)
)
unittest.main()
(类似于Perl中的Test::Deep
)
答案 0 :(得分:1)
这样的事情会起作用吗?
import unittest
from itertools import zip_longest
class RecursiveTestCase(unittest.TestCase):
def assertSequenceDeepEqual(self, x, y):
MissingValue = MissingValueSentinel()
for x, y, in zip_longest(x, y, fillvalue=MissingValue):
try:
self.assertSequenceDeepEqual(self, x, y)
except TypeError:
self.assertEqual(x, y)
self.assertIsNot(x, MissingValue)
self.assertIsNot(y, MissingValue)
class MissingValueSentinel(object):
pass
如果一个或多个项目不是迭代器,则 zip_longest
会引发TypeError
,表示您处于递归的底部。
如果其中一个迭代器比另一个迭代器短,我让它返回一个自定义MissingValueSentinel
对象,该对象由函数末尾的assertIsNot
调用检测到。这样做的唯一原因是,如果x
或y
有一个类,无论出于何种原因,它等于甚至是偶数类,如MissingValueSentinel
,但assertEqual
仍在在该类的两个不同对象之间有意义。这似乎是一个非常奇怪的边缘情况,你可以放心地忽略它。
使用zip_longest
代替zip
会阻止[1, 2, 3]
错误地匹配[1, 2]
。
答案 1 :(得分:1)
我遇到了与您类似的问题,但就我而言,我正在测试交付给API端点的数据结构。我最终要做的是比较每个值的标准化JSON序列化。这不是一个通用的解决方案,因为它将对无法序列化为JSON的任何值引发异常,但就我而言,这是一个功能,而不是一个错误,并且确实可以在您的示例情况下使用,所以我想我愿意
我创建了一个包含以下代码的tests/assertions.py
文件:
import json
class ApiAssertionsMixin(object):
def assertJsonEqual(self, first, second, msg=None):
j1 = json.dumps(first, sort_keys=True, indent=4)
j2 = json.dumps(second, sort_keys=True, indent=4)
self.maxDiff = None
self.assertEqual(j1, j2, msg)
在您的示例中,您将像这样使用它:
import unittest
from tests.assertions import ApiAssertionsMixin
class DeepCompareTestCase(ApiAssertionsMixin, unittest.TestCase):
def test_compare(self):
self.assertJsonEqual(
[['abc', 'def']],
(('abc', 'def'),)
)
unittest.main()
应该通过哪个。这是测试失败的示例:
def test_deep_compare(self):
self.assertJsonEqual(
{ 'name': 'Bob', 'aliases': ['Kate', 'Robbie'], 'age': 19 },
{ 'name': 'Bob', 'age': 20, 'aliases': ['Robbie'] }
)
具有这样的输出:
.F
======================================================================
FAIL: test_deep_compare (__main__.DeepCompareTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests/test_nested.py", line 18, in test_deep_compare
{ 'name': 'Bob', 'age': 20, 'aliases': ['Robbie'] }
File "./tests/assertions.py", line 10, in assertJsonEqual
self.assertEqual(j1, j2, msg)
AssertionError: '{\n "age": 19,\n "aliases": [\n "Kate",\n [41 chars]"\n}' != '{\n "age": 20,\n "aliases": [\n "Robbie"\n[24 chars]"\n}'
{
- "age": 19,
? ^^
+ "age": 20,
? ^^
"aliases": [
- "Kate",
"Robbie"
],
"name": "Bob"
}
----------------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (failures=1)
如您所见,如果发生故障,您将获得足够的背景信息来确定出了什么问题。
此方法的缺点是测试的输出是JSON而不是Python,因此,如果您从输出中复制/粘贴以修复测试,则需要翻译:{{1}} => { {1}},true
=> True
,false
=> False
。
答案 2 :(得分:0)
也许deepdiff模块有所帮助,但我没有对其进行测试。