如何测试 Django QuerySets 是不是相等?
Posted
技术标签:
【中文标题】如何测试 Django QuerySets 是不是相等?【英文标题】:How do I test Django QuerySets are equal?如何测试 Django QuerySets 是否相等? 【发布时间】:2013-07-15 03:13:45 【问题描述】:我正在尝试测试我的 Django 视图。此视图将 QuerySet 传递给模板:
def merchant_home(request, slug):
merchant = Merchant.objects.get(slug=slug)
product_list = merchant.products.all()
return render_to_response('merchant_home.html',
'merchant': merchant,
'product_list': product_list,
context_instance=RequestContext(request))
和测试:
def test(self):
"Merchant home view should send merchant and merchant products to the template"
merchant = Merchant.objects.create(name='test merchant')
product = Product.objects.create(name='test product', price=100.00)
merchant.products.add(product)
test_client = Client()
response = test_client.get('/' + merchant.slug)
# self.assertListEqual(response.context['product_list'], merchant.products.all())
self.assertQuerysetEqual(response.context['product_list'], merchant.products.all())
编辑
我使用self.assertQuerysetEqua
l 而不是self.assertListEqual
。不幸的是,这仍然不起作用,终端显示:
['<Product: Product object>'] != [<Product: Product object>]
assertListEqual
提出:'QuerySet' object has no attribute 'difference'
和
assertEqual
也不起作用,尽管 self.assertSetEqual(response.context['product_list'][0], merchant.products.all()[0])
确实通过了。
我认为这是因为 QuerySet 是不同的对象,即使它们包含相同的模型实例。
如何测试两个 QuerySet 是否包含相同的数据?我什至正确地测试了这个?这是我学习 Django 的第四天,所以如果可能的话,我想知道最佳实践。谢谢。
【问题讨论】:
相关:***.com/a/16059121 【参考方案1】:使用assertQuerysetEqual,它旨在为您比较两个查询集。您需要继承 Django 的 django.test.TestCase
才能在您的测试中使用它。
【讨论】:
太棒了,这很有帮助,尽管现在我的测试因此而失败: AssertionError: ['使用 pytest 时,另一种但不一定更好的方法可能如下所示(例如,在视图中测试上下文):
all_the_things = Things.objects.all()
assert set(response.context_data['all_the_things']) == set(all_the_things)
这会将其转换为一个集合,可以直接与另一个集合进行比较。请注意 set
的行为,但它可能不是您想要的,因为它会删除重复项并忽略对象的顺序。
【讨论】:
你可能不需要使用set(list())
,set()
就可以了。【参考方案3】:
默认情况下,assertQuerysetEqual
在第一个参数上使用 repr()
。这就是您在查询集比较中遇到字符串问题的原因。
要解决此问题,您可以在 override the transform
argument 中使用不使用 repr()
的 lambda
函数:
self.assertQuerysetEqual(queryset_1, queryset_2, transform=lambda x: x)
【讨论】:
我发现这也适用于比较具有相同键和相同查询集值的两个字典:self.assertQuerysetEqual(dict_1, dict_2, transform=lambda x: x)
【参考方案4】:
我发现使用self.assertCountEqual(queryset1, queryset2)
也可以解决问题。
【讨论】:
这不会为现有答案添加任何实质性内容。我建议改为支持这些答案。【参考方案5】:我最终使用map
到repr()
self.assertQuerysetEqual
调用中查询集中的每个条目解决了这个问题,例如
self.assertQuerysetEqual(queryset_1, map(repr, queryset_2))
【讨论】:
AssertionError: <QuerySet [<Account: Test Account>]> != <map object at 0x10c7f7ac8>
【参考方案6】:
我也遇到了同样的问题。 assertQuerysetEqual
的第二个参数需要是作为字符串的预期 repr() 列表。这是 Django 测试套件中的一个示例:
self.assertQuerysetEqual(c1.tags.all(), ["<Tag: t1>", "<Tag: t2>"], ordered=False)
【讨论】:
见***.com/a/14189017/678486(完全公开这是我的答案)。以上是关于如何测试 Django QuerySets 是不是相等?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Django QuerySets 时使用列表推导而不是 for 循环
如何使用 QuerySets 和 MySql“全文搜索”在多个字段中进行 Django 搜索?