比较django TestCase中的查询集

时间:2013-04-17 11:16:02

标签: django compare testcase django-queryset

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

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

5 个答案:

答案 0 :(得分:24)

如果查询集对象是不同查询的结果,则它们将不相同,即使它们的结果中具有相同的值(比较ds1.queryds2.query)。

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

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

答案 1 :(得分:6)

此替代方案不需要排序:

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

请参阅assert reference

注意:仅适用于django 1.4 +。

答案 2 :(得分:0)

找到解决方案。在我们比较它们之前,我们需要将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)))
    # ...

答案 3 :(得分:0)

对我来说,可以使用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)

答案 4 :(得分:0)

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

一个问题是,该方法在比较之前将 repr 函数作为对第一个参数中的每个对象的转换,这在比较两个实际相等的查询集时可能会导致以下错误:

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

解决方案是传递您自己的 transform 函数以代替 repr 使用:

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