为什么 pytest 有时会报告两个字典不相等?
Why does pytest sometimes report two dicts as unequal?
问题
我比较了两个词典,比如 d1
和 d2
,看起来像这样:
{
'id': 1,
'name': 'Foo',
'data': [
OrderedDict(('name', 'bar'), ('id', 3)),
],
}
当我断言这两个字典相等时,断言有时会失败。让我明白的是以下代码通过了:
for key in d1.keys():
assert d1[key] == d2[key]
任何人都可以阐明为什么会发生这种情况,以及为什么它看起来是随机发生的吗?
可能的原因
我在这里真正想做的是测试来自 Django Rest Framework 的序列化程序的输出。该数据并不总是作为普通字典返回,但针对非嵌套输出的其他测试按预期工作。
我还认为该断言可能无法测试嵌套列表,但以下内容通过无误:
d3 = {'data': d1['data']}
d4 = {'data': d2['data']}
assert d3 == d4
例子
我有两个模型,Foo
和 Bar
。每个 Bar
都属于一个 Foo
。我有以下序列化程序:
class BarSerializer(serializers.ModelSerializer):
class Meta:
fields = ('id', 'name')
model = Bar
class FooSerializer(serializers.ModelSerializer):
bars = BarSerializer(many=True, read_only=True)
class Meta:
fields = ('id', 'name', 'bars')
model = Foo
我正在尝试使用以下测试对 FooSerializer
的输出进行单元测试:
# Assume my_foo_instance is an instance of Foo with one associated Bar
# instance. This should avoid any problems with the ordering of BarSerializer
# affecting the outcome.
serializer = FooSerializer(my_foo_instance)
bar_serializer = BarSerializer(my_foo_instance.bars.all(), many=True)
expected = {
'id': my_foo_instance.id,
'name': my_foo_instance.name,
'bars': bar_serializer.data,
}
assert serializer.data == expected
正如我上面所说,断言有时会失败。
原来我没有提供足够的上下文来回答这个问题。我正在测试的序列化程序继承自另一个序列化程序,因此我没有手动构建测试中的所有字段,而是从基本序列化程序中提取字段,然后使用额外的预期内容更新该数据,如下所示:
base_serializer = BaseFooSerializer(foo)
additional = {
'more': 'attributes',
'of': 'foos',
}
expected = base_serializer.data.copy()
expected.update(additional)
assert foo_serializer.data == expected
因为 DRF 序列化器没有 return 标准的 Python 字典,我认为比较是不稳定的。为了修复它,我做了以下更正:
expected = dict(base_serializer.data.items())
现在一切正常。
问题
我比较了两个词典,比如 d1
和 d2
,看起来像这样:
{
'id': 1,
'name': 'Foo',
'data': [
OrderedDict(('name', 'bar'), ('id', 3)),
],
}
当我断言这两个字典相等时,断言有时会失败。让我明白的是以下代码通过了:
for key in d1.keys():
assert d1[key] == d2[key]
任何人都可以阐明为什么会发生这种情况,以及为什么它看起来是随机发生的吗?
可能的原因
我在这里真正想做的是测试来自 Django Rest Framework 的序列化程序的输出。该数据并不总是作为普通字典返回,但针对非嵌套输出的其他测试按预期工作。
我还认为该断言可能无法测试嵌套列表,但以下内容通过无误:
d3 = {'data': d1['data']}
d4 = {'data': d2['data']}
assert d3 == d4
例子
我有两个模型,Foo
和 Bar
。每个 Bar
都属于一个 Foo
。我有以下序列化程序:
class BarSerializer(serializers.ModelSerializer):
class Meta:
fields = ('id', 'name')
model = Bar
class FooSerializer(serializers.ModelSerializer):
bars = BarSerializer(many=True, read_only=True)
class Meta:
fields = ('id', 'name', 'bars')
model = Foo
我正在尝试使用以下测试对 FooSerializer
的输出进行单元测试:
# Assume my_foo_instance is an instance of Foo with one associated Bar
# instance. This should avoid any problems with the ordering of BarSerializer
# affecting the outcome.
serializer = FooSerializer(my_foo_instance)
bar_serializer = BarSerializer(my_foo_instance.bars.all(), many=True)
expected = {
'id': my_foo_instance.id,
'name': my_foo_instance.name,
'bars': bar_serializer.data,
}
assert serializer.data == expected
正如我上面所说,断言有时会失败。
原来我没有提供足够的上下文来回答这个问题。我正在测试的序列化程序继承自另一个序列化程序,因此我没有手动构建测试中的所有字段,而是从基本序列化程序中提取字段,然后使用额外的预期内容更新该数据,如下所示:
base_serializer = BaseFooSerializer(foo)
additional = {
'more': 'attributes',
'of': 'foos',
}
expected = base_serializer.data.copy()
expected.update(additional)
assert foo_serializer.data == expected
因为 DRF 序列化器没有 return 标准的 Python 字典,我认为比较是不稳定的。为了修复它,我做了以下更正:
expected = dict(base_serializer.data.items())
现在一切正常。