比较 django TestCase 中的查询集

问题描述 投票:0回答:8

我有一个非常简单的观点如下

def simple_view(request):
    documents = request.user.document_set.all()
    return render(request, 'simple.html', {'documents': documents})

为了在我的测试用例中测试上述视图,我有以下错误的方法。

Class SomeTestCase(TestCase):
    # ...
    def test_simple_view(self):
        # ... some other checks
        docset = self.resonse.context['documents']
        self.assertTrue(self.user.document_set.all() == docset) # This line raises an error
    # ...

我得到的错误是

AssertionError: False is not true
。 我尝试打印两个查询集,两者完全相同。当两个对象相同时,为什么它会返回
False
?有什么想法吗?

目前为了克服这个问题,我正在使用一种讨厌的方法来检查长度,如下所示:

ds1, ds2 = self.response.context['documents'], self.user.document_set.all()
self.assertTrue(len([x for x in ds1 if x in ds2]) == len(ds1) == len(ds2)) # Makes sure each entry in ds1 exists in ds2
django compare testcase django-queryset
8个回答
42
投票

如果查询集对象是不同查询的结果,即使它们的结果具有相同的值,它们也不会相同(比较

ds1.query
ds2.query
)。

如果您首先将查询集转换为列表,您应该能够进行正常的比较(当然假设它们具有相同的排序顺序):

self.assertEqual(list(ds1), list(ds2))

10
投票

这个替代方案不需要排序:

self.assertQuerysetEqual(qs1, list(qs2), ordered=False)

请参阅断言参考

注意:仅适用于 django 1.4+。


2
投票

如果你想检查 Django 查询集是否完全相同

self.assertEqual(str(simple_qs.query), str(complex_qs.query))


2
投票

您可以使用 assertQuerySetEqual 方法来比较两个查询集,而无需转换为列表。如果查询集的值相等,则无论查询是否不同,都会返回

True

一个问题是,此方法在比较之前将

repr
函数作为转换应用于第一个参数中的每个对象,这在比较两个实际上相等的查询集时可能会导致以下错误:

AssertionError: Lists differ: ['<Object: id1'] != [<Object: id1>]

解决方案是传递您自己的

transform
函数来代替
repr
:

self.assertQuerySetEqual(qs1, qs2, transform=lambda x: x)

1
投票

对我来说,

transform
选项有效:

    def subject(self):
        return Mission.objects.add_keynest_api_token().filter(keynest_api_token__isnull=False)

    def test_mission_has_property(self):
        self.mission.appartement = self.property
        self.mission.save()
        self.assertQuerysetEqual(self.subject(), [self.mission], transform=lambda x: x)


0
投票

如果您想断言两个查询集的内容相等而不用担心顺序,请使用以下命令:

self.assertQuerysetEqual(actual_queryset, expected_queryset, transform=lambda x: x, ordered=False)

-1
投票

找到解决方案。在比较它们之前,我们需要将

Querysets
转换为排序列表。如下。

Class SomeTestCase(TestCase):
    # ...
    def test_simple_view(self):
        # ... some other checks
        docset1 = self.resonse.context['documents']
        docset2 = self.user.document_set.all()
        self.assertTrue(list(sorted(docset1)) == len(sorted(docset)))
    # ...

-1
投票
def test_simple_view(self):
    # ... some other checks
    docset = set([i.pk for i in self.resonse.context['documents']])
    prev = set([i.pk for i in self.user.document_set.all()])
    diff = prev.difference(docset)
    self.assertTrue(len(diff)==0)
© www.soinside.com 2019 - 2024. All rights reserved.