如何在Python中单元测试包含字符串与字典值的嵌套字典?
嘿,我来帮你搞定这个嵌套字典的单元测试问题!
先用unittest自带方法直接解决
其实你可能没注意到,Python unittest.TestCase 里的 assertDictEqual 本身就支持递归比较嵌套字典!就像你给出的例子,直接用它就能通过测试:
import unittest class TestNestedDictEquality(unittest.TestCase): def test_basic_nested_dicts(self): x = {'type': 'example', 'color': 'blue', 'entries_dict':{'clock':'c', 'id': 1}} y = {'color': 'blue', 'entries_dict':{'id': 1, 'clock':'c'}, 'type': 'example'} self.assertDictEqual(x, y) # 这个测试会顺利通过!
原因很简单:assertDictEqual 不会纠结字典的键顺序(哪怕Python 3.7+字典保留插入顺序,断言时只关心键值对的内容匹配),而且会自动递归遍历所有嵌套的字典,逐一校验里面的每一组键值对。
自定义递归比较(应对更复杂场景)
如果你的实际业务里还有更复杂的结构(比如嵌套列表、自定义类实例,或者需要忽略某些动态变化的键),那自己实现一个递归比较函数确实是更灵活的选择。这里给你一个实用的版本:
def deep_dict_equal(a, b, exclude_keys=None): exclude_keys = exclude_keys or set() # 先检查类型是否一致 if type(a) != type(b): return False # 处理字典类型:递归比较每个键值对(跳过排除键) if isinstance(a, dict): a_keys = set(a.keys()) - exclude_keys b_keys = set(b.keys()) - exclude_keys if a_keys != b_keys: return False for key in a_keys: if not deep_dict_equal(a[key], b[key], exclude_keys): return False return True # 处理可迭代对象(排除字符串,因为字符串也算可迭代) elif isinstance(a, (list, tuple, set)) and not isinstance(a, str): # 如果需要无序比较就用sorted,要有序就去掉sorted return len(a) == len(b) and all(deep_dict_equal(x, y, exclude_keys) for x, y in zip(sorted(a), sorted(b))) # 基础类型直接比较值 else: return a == b
然后在单元测试里这样用:
class TestComplexNestedDicts(unittest.TestCase): def test_advanced_nested_structures(self): x = { 'type': 'example', 'data': [{'id': 1}, {'id': 2}], 'meta': {'key': {'subkey': 'value'}}, 'timestamp': 1690000000 # 这个键我们想忽略 } y = { 'meta': {'key': {'subkey': 'value'}}, 'type': 'example', 'data': [{'id': 2}, {'id': 1}], 'timestamp': 1690000001 } # 忽略timestamp键,测试通过 self.assertTrue(deep_dict_equal(x, y, exclude_keys={'timestamp'}))
这个函数不仅能处理多层嵌套的字典,还能应对列表、元组这类可迭代对象的比较,甚至支持跳过指定的无关键。
额外小提示
- 如果你用的是
pytest而不是原生unittest,直接写assert x == y就行——pytest的断言会自动递归比较嵌套结构,而且失败时会给出非常详细的差异提示,比unittest更友好。 - 如果需要处理自定义类的实例,可以在函数里加专门的判断逻辑,比如检查实例的属性是否匹配。
内容的提问来源于stack exchange,提问作者Dax Gray
相关产品推荐
相关产品推荐

