我有一个非常简单的观点如下
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
如果查询集对象是不同查询的结果,即使它们的结果具有相同的值,它们也不会相同(比较
ds1.query
和 ds2.query
)。
如果您首先将查询集转换为列表,您应该能够进行正常的比较(当然假设它们具有相同的排序顺序):
self.assertEqual(list(ds1), list(ds2))
如果你想检查 Django 查询集是否完全相同
self.assertEqual(str(simple_qs.query), str(complex_qs.query))
您可以使用 assertQuerySetEqual 方法来比较两个查询集,而无需转换为列表。如果查询集的值相等,则无论查询是否不同,都会返回
True
。
一个问题是,此方法在比较之前将
repr
函数作为转换应用于第一个参数中的每个对象,这在比较两个实际上相等的查询集时可能会导致以下错误:
AssertionError: Lists differ: ['<Object: id1'] != [<Object: id1>]
解决方案是传递您自己的
transform
函数来代替 repr
:
self.assertQuerySetEqual(qs1, qs2, transform=lambda x: x)
对我来说,
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)
如果您想断言两个查询集的内容相等而不用担心顺序,请使用以下命令:
self.assertQuerysetEqual(actual_queryset, expected_queryset, transform=lambda x: x, ordered=False)
找到解决方案。在比较它们之前,我们需要将
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)))
# ...
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)