如何测试断言两个包含字典列表(其中一个字典项包含一个列表)的列表是否相同?

6

我正在创建我的第一个测试脚本(耶!)。 我有一个字典列表,其中一个键是列表。 如果字典中的列表可以以任何顺序出现,我希望测试通过。 我知道你可以使用 assertCountEqual 来检查列表的相等性,而不考虑顺序,但是对于包含字典列表的列表,是否也可以这样做?请参见下面的示例。

将成功

def test(self):
    output = [2,1]
    desired_output = [1,2]
    self.assertCountEqual(output, desired_output)

将会失败

def test(self):
    desired_output = [{'count': 2, 'columns': ['col2', 'col5']}]
    output = [{'count': 2, 'columns': ['col5', 'col2']}]
    self.assertCountEqual(output, desired_output)

谢谢


您是否需要在字典中使用列表?如果顺序无关紧要,为什么不改用集合? - dspencer
你可以尝试对每个列表进行排序。无论是在单元测试中还是其他情况下,当你需要频繁比较差异时,排序总是值得考虑的。@dspencer - 在集合中,重复项会被删除,导致错误的相等性。 - JL Peyret
1
好的,@dspencer。我不需要使用列表。集合对我也有用。 - Micah Pearce
1个回答

5

assertCountEqual(first, second, msg=None)

测试序列first是否包含与second相同的元素,无论它们的顺序如何。当它们不同时,将生成一个列出两个序列之间差异的错误消息。

重要提示:

调用assertCountEqual(first, second, msg=None)等效于assertEqual(Counter(list(first)), Counter(list(second)))

注:

计数器是可哈希对象计数的字典子类。它是一个集合,其中元素被存储为字典键,并且它们的计数被存储为字典值。 为了使其工作,键必须是可哈希的,但不幸的是,dict不可哈希的,因为它是可变的。


为了执行所需的任务,您可以使用frozensetfrozenset构建了一个不可变的无序独特元素的集合。 为了使测试成功,您将需要构建一个字典,其中对应于其键的值是不可变的。我们可以使用递归方法来构建包含不可变值的字典。

试试这个(更新):

def getHashableDict(dictionary):
    hashable_dict = {}
    for key, value in dictionary.items():
        if isinstance(value, list):
            hashable_dict[key] = frozenset(value)
        elif isinstance(value, dict):
            hashable_dict[key] = getHashableDict(value)
        else:
            hashable_dict[key] = value

    return frozenset(hashable_dict.items())

def test(self):
    desired_output = [{'count': 2, 'columns': ['col2', 'col5']}]
    output = [{'count': 2, 'columns': ['col5', 'col2']}]

    output = [getHashableDict(item) for item in output] #--> create list of hashable types
    desired_output = [getHashableDict(item) for item in desired_output]

    self.assertCountEqual(output, desired_output)

测试现在将会成功。


在现代(CPython/PyPy的3.6+,语言保证为3.7)中,默认情况下,dict是按插入顺序排序的;Counter继承了这种行为,因此它不是无序的,正如你所说的那样;键按它们第一次被计数时出现的顺序排序。 - ShadowRanger
1
聪明!@dspencer 指出在这种情况下集合同样适用。至少在我的使用中是这样的。然而,这也解决了问题,我学到了东西。谢谢! - Micah Pearce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接