为什么pytest有时会将两个dicts报告为不相等?

时间:2018-02-20 23:40:29

标签: python django-rest-framework pytest

问题

我对两个词典进行了比较,比如d1d2,看起来像这样:

{
    '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

实施例

我有两个模型,FooBar。每个BarFoo所有。我有以下序列化器:

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

如上所述,断言有时失败。

1 个答案:

答案 0 :(得分:0)

事实证明,我没有提供足够的背景来回答这个问题。我测试的序列化程序继承自另一个序列化程序,因此我不是手动构建测试中的所有字段,而是从基本序列化程序中提取字段,然后使用其他预期内容更新该数据,如下所示:

base_serializer = BaseFooSerializer(foo)

additional = {
    'more': 'attributes',
    'of': 'foos',
}

expected = base_serializer.data.copy()
expected.update(additional)

assert foo_serializer.data == expected

由于DRF序列化程序不会返回标准的Python字典,我认为这种比较很糟糕。为了解决这个问题,我做了以下修正:

expected = dict(base_serializer.data.items())

现在它运作正常。