【问题标题】:How to test views that use post request in django?如何在 django 中测试使用 post 请求的视图?
【发布时间】:2017-09-16 00:39:29
【问题描述】:

这是我的观点(简化):

@login_required(login_url='/try_again')
def change_bar(request):
    foo_id = request.POST['fid']
    bar_id = request.POST['bid']
    foo = models.Foo.objects.get(id=foo_id)
    if foo.value > 42:
            bar = models.Bar.objects.get(id=bar_id)
            bar.value = foo.value
            bar.save()
    return other_view(request)

现在我想检查一下这个视图是否正常工作(在这个简化的模型中,如果 Bar 实例在它应该改变值的时候改变了值)。我该怎么办?

【问题讨论】:

  • 您可以尝试在代码之间放置“打印”语句,看看是否保存了正确的值。对于更新而不是使用“get”查询然后保存(bar.save),您可以使用“filter”和“update”方法。

标签: django django-models django-views http-post django-testing


【解决方案1】:

您可以尝试在代码之间放置“打印”语句,看看是否保存了正确的值。同样对于更新而不是使用“get”查询然后保存它(bar.save()),您可以使用“filter”和“update”方法。

@login_required(login_url='/try_again')
def change_bar(request):
foo_id = request.POST['fid']
bar_id = request.POST['bid']
foo = models.Foo.objects.get(id=foo_id)
if foo.value > 42:
        models.Bar.objects.filter(id=bar_id).update(value=foo.value)
        #bar.value = foo.value
        #bar.save()
return other_view(request)

【讨论】:

  • 感谢 .update() 方法。至于测试,我在考虑 UnitTests,而不仅仅是“手动检查”。
【解决方案2】:

我将假设您的意思是自动化测试,而不仅仅是检查发布请求是否有效。如果您的意思是后者,只需执行请求并在 shell 或管理员中检查相关 FooBar 的值即可。

发送POST 请求的最佳方式是使用Client。假设视图的名称是my_view

from django.test import Client
from django.urls import reverse

c = Client()
c.post(reverse('my_view'), data={'fid':43, 'bid':20})

但是您仍然需要数据库中的一些初始数据,并且您需要检查是否进行了您期望进行的更改。这是你可以使用TestCase的地方:

from django.test import TestCase, Client
from django.urls import reverse

FooBarTestCase(TestCase):

def setUp(self):
    # create some foo and bar data, using foo.objects.create etc
    # this will be run in between each test - the database is rolled back in between tests

def test_bar_not_changed(self):
    # write a post request which you expect not to change the value 
    # of a bar instance, then check that the values didn't change
    self.assertEqual(bar.value, old_bar.value)

def test_bar_changes(self):
    # write a post request which you expect to change the value of 
    # a bar instance, then assert that it changed as expected
    self.assertEqual(foo.value, bar.value)

FactoryBoy 是一个我认为有助于设置一些数据以更轻松地执行测试的库。在为测试目的创建 FooBar 的新实例时,它减少了样板文件。另一种选择是编写固定装置,但如果你的模型发生变化,我发现它的灵活性会降低。

如果您想了解更多关于 python 测试的信息,我也推荐this book。它是面向 django 的,但原则适用于其他框架和上下文。

编辑:添加了关于 factoryboy 的建议和书籍链接

【讨论】:

  • 非常感谢 :) 我设法让这个测试工作了!我必须添加from django.contrib.auth.models import User ### self.user = User.objects.create_user(username='abc', password='abc') ### c.login(username='abc', password='abc') 以满足@login_required。还发现self.assertEqual(self.bar.value, good_value) 由于某种原因不起作用(这是我在setUp(self) 中创建的bar)。不得不改用self.assertEqual(Bar.objects.get(id=self.bid).value, good_value)(得到相同的(?)条)。
  • 啊,很好,很高兴它成功了! self.assertEqual(Bar.objects.get(id=self.bid).value, good_value) 从数据库中重新检索您的 Bar 对象,这意味着它是“相同的”Bar(因为它具有相同的主键),但它会随着您通过触发 @987654342 所做的更改而更新@ 要求。您可以通过调用self.bar.refresh_from_db() 来实现相同的目的,这会使用数据库中的最新信息更新您的python 对象self.bar
猜你喜欢
  • 1970-01-01
  • 2020-08-15
  • 2015-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-22
  • 1970-01-01
  • 2019-12-01
相关资源
最近更新 更多