【问题标题】:How to write tests for custom Django generic view?如何为自定义 Django 通用视图编写测试?
【发布时间】:2019-01-05 08:09:08
【问题描述】:

我不明白我们应该为 Django 视图编写测试的方式。因为,我的情况与其他人不同。

我有一个视图,比如说 MyView,它继承自基于 Django 通用类的视图的 CreateView。但是,在后台,我的意思是在 form_valid 函数中,该视图尝试使用 Python 库连接到远程服务器,然后根据用户的输入获取数据,然后处理其他细节并保存对象,如果一切正常,如果没有,它会返回自定义错误。

我应该如何处理这种视图以便编写测试?

(我可以使用类似的东西,但处理可能的错误并不好:

from django.test import Client
c = Client()
c.login(mydetails..)

y = c.post('/url/', {'my': 'data'})

它有效,是的,但我只在这种情况下检查状态代码。 y.status_code 没办法,因为即使表单出现错误,Django 也会返回 200。

【问题讨论】:

    标签: django django-testing


    【解决方案1】:

    为了简化 django 中的测试框架,测试将模拟客户端请求(如用户单击链接“url”),此 url 与将处理请求并向用户返回响应的视图相关联。例如,在您的测试中,您将断言视图是否呈现正确的响应和模板。假设我们有一个创建博客的视图,如何进行测试?请看下面的代码。

    views.py

    def createblog_view(request):
        if request.method == 'POST':
            form = BlogForm(request.POST)
            if form.is_valid():
                blog = form.save(commit=False)
                blog.author = request.user  # save the user who created the blog
                blog.save()
                return redirect(blog.get_absolute_url())
        else:
            form = BlogForm()
        context = {'form': form}
        return render(request, 'blog/createblog.html', context)
    

    test.py

    class BlogTest(TestCase):
            def setUp(self):
                # this user will be used to create the blog
                self.user = User.objects.create_superuser(
                    'foo',
                    'foo@test.com',
                    'password'
                )
    
            def test_create_blog(self): # create update and delete a blog
                # log user in and user 
                self.client.login(username='foo', password='password')
    
                # create new blog
                # expected date from the user, you can put invalid data to test from validation
                form_data = { 
                    'title': 'new test blog',
                    'body': 'blog body'
                } 
                form = BlogForm(data=blogform_data) # create form indstance 
    
                """
                simulate post request with self.client.post
                /blog/createblog/ is the url associated with create_blog view
                """
                response = self.client.post('/blog/createblog/', form_data)
                # get number of created blog to be tested later
                num_of_blogs = Blog.objects.all().count()
                # get created blog
                blog = Blog.objects.get(title=form_data['title'])
                # test form validation
                self.assertTrue(blogform.is_valid())
                # test slugify method, if any
                self.assertEqual(blog.slug, 'new-test-blog')
                # test if the blog auther is the same logged in user
                self.assertEqual(blog.author, self.user1)
                # one blog created, test if this is true
                self.assertEqual(num_of_blogs, 1)
                # test redirection after blog created
                self.assertRedirects(
                    createblog_response,
                    '/blog/new-test-blog/',
                    status_code=302,
                    target_status_code=200
                )
    

    【讨论】:

    • 谢谢,但我没有从你的例子中得到我的所有需要​​。也许我跳过了一些重要的点。让我以不同的方式解释我的情况。我有一个观点,要创建一篇博文(仅作为示例)。我在表单中向用户显示标题和描述字段,但我的视图也有“xyz 字段”要从远程 API 填写。用户填写标题和描述字段并提交表单。然后我的视图根据用户输入从远程 API 获取附加数据。如果一切正常,我的视图会将来自 API 的附加数据添加到表单/对象实例中。然后保存。
    • 我是否也需要在测试类中模拟同样的事情(在我看来从远程 API 获取数据)?我的意思是,我不能直接使用您的form = BlogForm(data=blogform_data) 行。因为我的表单需要额外的数据.. 呃.. 你没有使用 form 变量所以也许我根本不需要这一行?您是否添加了这一行来描述某事?
    • 我添加了这一行来获取表单实例,以便稍后检查它是否有效,这是唯一的原因。您的 api 数据在您的视图中处理,因此您无需将任何额外数据传递给 form_data。您可以从模型中检索创建的对象并检查 api 字段是否按预期填充。你能告诉我你的观点以便更好地理解吗?
    • 啊,我明白了!实际上,不再需要查看视图,我不想让您感到疲倦,因为感谢您的最新评论,我已经了解了一切。非常感谢您的帮助。
    • 不客气。很高兴听到我的回答很有用:)
    猜你喜欢
    • 1970-01-01
    • 2018-05-10
    • 1970-01-01
    • 2014-07-14
    • 2023-03-18
    • 2015-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多