我如何测试Django QuerySets是否相等?

时间:2013-07-16 19:09:54

标签: python django django-queryset django-testing

我正在尝试测试我的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])确实通过了。

我认为这是因为QuerySets是不同的对象,即使它们包含相同的模型实例。

如何测试两个QuerySets包含相同的数据?我甚至正确测试了这个?这是我第四天学习Django,所以如果可能的话,我想了解最佳实践。感谢。

5 个答案:

答案 0 :(得分:23)

使用assertQuerysetEqual,它是为了比较两个查询集而构建的。您需要继承Django的django.test.TestCase子类才能在测试中使用它。

答案 1 :(得分:18)

默认情况下assertQuerysetEqual在第一个参数上使用repr()。这就是您在查询集比较中遇到字符串问题的原因。

要解决此问题,您可override the transform argument使用lambda功能,但不能使用repr()

self.assertQuerysetEqual(queryset_1, queryset_2, transform=lambda x: x)

答案 2 :(得分:3)

我最终使用SELECT TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME, REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_SCHEMA = '<database>' map repr()调用内的查询集中的每个条目来解决此问题,例如

self.assertQuerysetEqual

答案 3 :(得分:1)

使用pytest时,另一种(但不一定是更好的)方法可能看起来像这样(例如,在视图中测试上下文):

all_the_things = Things.objects.all()
assert set(list(response.context_data['all_the_things'])) == set(list(all_the_things))

将其转换为列表,然后转换为集合,可直接与其他集合进行比较。但请注意set的行为,它可能不是您想要的,因为它会删除重复项。

答案 4 :(得分:0)

我发现使用self.assertCountEqual(queryset1, queryset2)也解决了这个问题。