在Django的TestCase比较查询集(comparing querysets in djang

2019-08-31 09:37发布

我有一个非常简单的看法如下

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

Answer 1:

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

如果转换查询设为榜第一,你应该能够做一个比较正常的(假设他们当然有相同的排序顺序):

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


Answer 2:

这种替代不需要排序:

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

见断言参考 。

注意:仅适用于Django的1.4+。



Answer 3:

找到了解决办法。 我们需要转换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)))
    # ...


文章来源: comparing querysets in django TestCase