sap*_*api 18 python unit-testing python-unittest
我知道,在assertEqual字典上执行时,会assertDictEqual被调用.同样,assertEqual序列将执行assertSequenceEqual.
但是,在assertDictEqual比较值时,似乎没有使用assertEqual,因此assertSequenceEqual不会被调用.
请考虑以下简单的词典:
lst1 = [1, 2]
lst2 = [2, 1]
d1 = {'key': lst1}
d2 = {'key': lst2}
self.assertEqual(lst1, lst2) # True
self.assertEqual(d1, d2) # False ><
Run Code Online (Sandbox Code Playgroud)
我如何通过递归地将类似语义应用于值来测试诸如d1并d2正确比较它们的相等的字典assertEqual?
我想尽可能避免使用外部模块(如本问题所示),除非它们是本机django扩展.
编辑
基本上,我所追求的是这个的内置版本:
def assertDictEqualUnorderedValues(self, d1, d2):
for k,v1 in d1.iteritems():
if k not in d2:
self.fail('Key %s missing in %s'%(k, d2))
v2 = d2[k]
if isinstance(v1, Collections.iterable) and not isinstance(v1, basestring):
self.assertValuesEqual(v1, v2)
else:
self.assertEqual(v1, v2)
Run Code Online (Sandbox Code Playgroud)
上面代码的问题是错误消息不如内置断言那么好,并且可能存在我忽略的边缘情况(因为我刚刚写了这篇文章).
而不是重写assertDictEqual,为什么不首先递归排序你的dicts?
def deep_sort(obj):
"""
Recursively sort list or dict nested lists
"""
if isinstance(obj, dict):
_sorted = {}
for key in sorted(obj):
_sorted[key] = deep_sort(obj[key])
elif isinstance(obj, list):
new_list = []
for val in obj:
new_list.append(deep_sort(val))
_sorted = sorted(new_list)
else:
_sorted = obj
return _sorted
Run Code Online (Sandbox Code Playgroud)
然后排序,并使用正常的assertDictEqual:
dict1 = deep_sort(dict1)
dict2 = deep_sort(dict2)
self.assertDictEqual(dict1, dict2)
Run Code Online (Sandbox Code Playgroud)
这种方法的好处是不关心列表的深度.
该TestCase.assertEqual()方法调用类' assertDictEqual()for dicts,因此只需在您的子类派生中覆盖它。如果您只assertXXX在方法中使用其他方法,错误消息应该几乎和内置断言一样好——但如果不是,您可以msg在调用它们时提供关键字参数来控制显示的内容。
import collections
import unittest
class TestSOquestion(unittest.TestCase):
def setUp(self):
pass # whatever...
def assertDictEqual(self, d1, d2, msg=None): # assertEqual uses for dicts
for k,v1 in d1.iteritems():
self.assertIn(k, d2, msg)
v2 = d2[k]
if(isinstance(v1, collections.Iterable) and
not isinstance(v1, basestring)):
self.assertItemsEqual(v1, v2, msg)
else:
self.assertEqual(v1, v2, msg)
return True
def test_stuff(self):
lst1 = [1, 2]
lst2 = [2, 1]
d1 = {'key': lst1}
d2 = {'key': lst2}
self.assertItemsEqual(lst1, lst2) # True
self.assertEqual(d1, d2) # True
if __name__ == '__main__':
unittest.main()
Run Code Online (Sandbox Code Playgroud)
输出:
import collections
import unittest
class TestSOquestion(unittest.TestCase):
def setUp(self):
pass # whatever...
def assertDictEqual(self, d1, d2, msg=None): # assertEqual uses for dicts
for k,v1 in d1.iteritems():
self.assertIn(k, d2, msg)
v2 = d2[k]
if(isinstance(v1, collections.Iterable) and
not isinstance(v1, basestring)):
self.assertItemsEqual(v1, v2, msg)
else:
self.assertEqual(v1, v2, msg)
return True
def test_stuff(self):
lst1 = [1, 2]
lst2 = [2, 1]
d1 = {'key': lst1}
d2 = {'key': lst2}
self.assertItemsEqual(lst1, lst2) # True
self.assertEqual(d1, d2) # True
if __name__ == '__main__':
unittest.main()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
26430 次 |
| 最近记录: |