Python 单元测试 - 使用列表断言字典

问题描述 投票:0回答:5

在为我的班级编写一些测试时,我遇到了有趣的简单问题。我想断言两个字典包含一些列表。但是这个列表可能不会以相同的方式排序 -> 这会导致测试失败

示例:

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
或在比较之前对列表进行排序。

python unit-testing dictionary assert
5个回答
8
投票

您可以尝试PyHamcrest(示例已更正)

assert_that(obj.exportToDict(), has_entries(
                                    { 'state': 2347,
                                      'neighbours': contains_inanyorder(1,2,3) }))

(第一个值 2347 实际上被包装在隐式

equal_to
匹配器中。)


2
投票

你可以这样做:

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)

0
投票

如何使用

all
:

assert all( (k,v) in resulting_dictionary.iteritems() 
            for (k,v) in obj.exportToDict().iteritems() )

我在 py.test 中使用了类似的东西,但我认为它应该适合你。


一位评论者指出,这个顺序会把我搞砸了——这很公平……那么我就用套装吧。


0
投票

也许您可以分别检查这两个元素:

obj_dict = obj.exportToDict()
self.assertEqual(resulting_dictionary['state'], obj_dict['state'])
self.assertCountEqual(resulting_dictionary['neighbours'], obj_dict['neighbours'])

0
投票

您可以使用以下辅助函数:

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
© www.soinside.com 2019 - 2024. All rights reserved.