Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用应用于值的assertSequenceEqual实现assertDictEqual_Python_Unit Testing_Python Unittest - Fatal编程技术网

Python 如何使用应用于值的assertSequenceEqual实现assertDictEqual

Python 如何使用应用于值的assertSequenceEqual实现assertDictEqual,python,unit-testing,python-unittest,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(lst

我知道,在字典上执行
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 ><

上面代码的问题是错误消息没有内置断言的那么好,并且可能有一些我忽略的边缘情况(正如我刚才在头上写的那样)。TestCase.assertEqual()方法为
dicts调用类'
assertDictEqual()
,所以只需在子类派生中重写它。如果在方法中只使用其他
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()
输出:

python unittest\u test.py . ----------------------------------------------------------------------> 在0.000秒内运行了1次测试 好啊 >
与其重写assertDictEqual,不如先对DICT进行递归排序

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
然后进行排序,并使用普通assertDictEqual:

    dict1 = deep_sort(dict1)
    dict2 = deep_sort(dict2)

    self.assertDictEqual(dict1, dict2)

这种方法的好处是不关心列表的深度。

我也有同样的问题,我必须测试模型的字段是否正确。和MyModel._meta.get_all_field_names()有时返回['a','b'],有时返回['b','a']

当我跑步时:

self.assertEqual(MyModel._meta.get_all_field_names(), ['a', 'b'])
它有时会失败

我通过将两个值放在一个集合()中解决了这个问题:

这在以下情况下不起作用(返回True):


但是,由于我正在检查模型的字段名,并且这些字段名是唯一的,这对我来说很好。

对于
unittest
模块,
self.assertEqual(lst1,lst2)
不是真的-->
AssertionError:list不同:[1,2]!=[2,1]
@martineau-我的错误;我误读了文件的那一部分。我在寻找一个等价的
asserteSequal
而不是
assertSequenceEqual
好吧,如果你使
lst1
lst2
相同,那么第一个
assertEqual
成功,那么第二个也会成功“正在寻找与
AssertSequenceQual
等效的,而不是
assertSequenceEqual
“对我来说毫无意义。我的观点是,您问题中的代码在两个列表上使用的是
assertEqual
,两个列表中的项顺序不同,该断言将失败。如果您控制创建数据结构的代码,可能应该使用集合而不是列表。我无法保证列表的顺序。这些测试是针对django框架的,我不能依赖于测试集和预期结果之间的数据库查询顺序是相同的。我所关心的是API以某种顺序给了我正确的值。好吧,但我仍然不明白为什么/如何期望第一个
assertEqual(lst1,lst2)
在代码中为真。此解决方案不适用于深度嵌套的dicts+列表。基于排序的解决方案确实如此。您可以使用集合表示法来改进这一点,而不是
set(['a','b'])
尝试
{'a','b'}
。此外,还有一个函数
self.assertSetEqual({'a','a','b','a'},{'a','b'})
,它将检查两个集合之间的差异,如果它们不包含完全相同的元素,则会失败。
Exception:'
self.assertEqual(MyModel._meta.get_all_field_names(), ['a', 'b'])
self.assertEqual(set(MyModel._meta.get_all_field_names()), set(['a', 'b'])) #true

self.assertEqual(set(MyModel._meta.get_all_field_names()), set(['b', 'a'])) #true
self.assertEqual(set(['a','a','b','a']), set(['a','b']))  # Also true