在为我的班级编写一些测试时,我遇到了有趣的简单问题。我想断言两个字典包含一些列表。但是这个列表可能不会以相同的方式排序 -> 这会导致测试失败
示例:
def test_myobject_export_into_dictionary(self):
obj = MyObject()
resulting_dictionary = {
'state': 2347,
'neighbours': [1,2,3]
}
self.assertDictEqual(resulting_dictionary, obj.exportToDict())
这有时会失败,具体取决于列表中元素的顺序
FAIL: test_myobject_export_into_dictionary
------------------------------------
- 'neighbours': [1,2,3],
+ 'neighbours': [1,3,2],
有什么想法如何以简单的方式断言这一点吗?
我正在考虑使用
set
而不是 list
或在比较之前对列表进行排序。
您可以尝试PyHamcrest(示例已更正)
assert_that(obj.exportToDict(), has_entries(
{ 'state': 2347,
'neighbours': contains_inanyorder(1,2,3) }))
(第一个值 2347 实际上被包装在隐式
equal_to
匹配器中。)
你可以这样做:
a = {i:sorted(j) if isinstance(j, list) else j for i,j in resulting_dictionary.iteritems()}
b = {i:sorted(j) if isinstance(j, list) else j for i,j in obj.exportToDict().iteritems()}
self.assertDictEqual(a, b)
如何使用
all
:
assert all( (k,v) in resulting_dictionary.iteritems()
for (k,v) in obj.exportToDict().iteritems() )
我在 py.test 中使用了类似的东西,但我认为它应该适合你。
一位评论者指出,这个顺序会把我搞砸了——这很公平……那么我就用套装吧。
也许您可以分别检查这两个元素:
obj_dict = obj.exportToDict()
self.assertEqual(resulting_dictionary['state'], obj_dict['state'])
self.assertCountEqual(resulting_dictionary['neighbours'], obj_dict['neighbours'])
您可以使用以下辅助函数:
def sort_lists(item):
"""
Takes a dict or list and modifies it in place so that all nested lists are sorted.
"""
if isinstance(item, list):
if len(item) > 0:
# Check if the first element of the list is itself a list or dict
if isinstance(item[0], (list, dict)):
for i in item:
sort_lists(i)
else:
item.sort()
elif isinstance(item, dict):
for key, value in item.items():
sort_lists(value)
可以这样使用:
>>> from unittest import TestCase
>>> dict_w_lists = {"one": [3, 2, 1], "two": [7, 4, 2]}
>>> TestCase().assertDictEqual(dict_w_lists, {"one": [1, 2, 3], "two": [2, 4, 7]})
Traceback (most recent call last):
<...>
AssertionError: {'one': [3, 2, 1], 'two': [7, 4, 2]} != {'one': [1, 2, 3], 'two': [2, 4, 7]}
- {'one': [3, 2, 1], 'two': [7, 4, 2]}
? ^ ^ ^ ^
+ {'one': [1, 2, 3], 'two': [2, 4, 7]}
? ^ ^ ^ ^
>>> sort_lists(dict_w_lists)
>>> TestCase().assertDictEqual(dict_w_lists,{"one": [1, 2, 3], "two": [2, 4, 7]})
>>> # test passes