如何在 django 中测试使用 post 请求的视图?

Jec*_*cke 2 django http-post django-models django-views django-testing

这是我的观点(简化):

@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)
Run Code Online (Sandbox Code Playgroud)

现在我想检查此视图是否正常工作(在这个简化的模型中,Bar 实例是否在应该时更改值)。我该怎么办?

Fra*_*rES 6

我假设您的意思是自动化测试,而不仅仅是检查发布请求是否有效。如果您确实指的是后者,只需通过执行请求并在 shell 或管理员中检查相关Foo和的值来进行检查。Bar

发送请求的最佳方法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})
Run Code Online (Sandbox Code Playgroud)

但是您仍然需要数据库中的一些初始数据,并且需要检查是否进行了预期的更改。这是你可以使用的地方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)
Run Code Online (Sandbox Code Playgroud)

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

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

编辑:添加了有关 Factoryboy 的建议和书籍链接

  • 啊,很好,很高兴成功了!`self.assertEqual(Bar.objects.get(id=self.bid).value, good_value)` 从数据库中重新检索您的 `Bar` 对象,这意味着它是“相同的” `Bar` (因为它具有相同的主键),但它会根据您通过触发“POST”请求所做的更改进行更新。您可以通过调用 self.bar.refresh_from_db() 来实现相同的目的,它会使用数据库中的最新信息更新您的 python 对象 self.bar 。 (2认同)