我应该如何在Django中为表单编写测试?

120

我希望在编写测试时能够模拟请求到我的 Django 视图,主要是为了测试表单。下面是一个简单测试请求的代码片段:

from django.tests import TestCase

class MyTests(TestCase):
    def test_forms(self):
        response = self.client.post("/my/form/", {'something':'something'})
        self.assertEqual(response.status_code, 200) # we get our page back with an error

无论表单是否有错误,该页面始终返回200的响应。我该如何检查我的表单是否失败以及特定字段(something)是否有错误?

3个回答

275

我认为如果你只想测试表单,那么你应该只测试表单,而不是呈现表单的视图。以下是一个示例以获取想法:

from django.test import TestCase
from myapp.forms import MyForm

class MyTests(TestCase):
    def test_forms(self):
        form_data = {'something': 'something'}
        form = MyForm(data=form_data)
        self.assertTrue(form.is_valid())
        ... # other tests relating forms, for example checking the form data

64
单元测试的概念是分别测试每个单元。 - Daniel Roseman
14
但是集成测试更有用,更有可能发现错误。 - wobbily_col
21
在集成测试中,更难发现实际的缺陷,需要花费更多时间才能找出。而在单元测试中,这一点更加明显。我认为,为了获得良好的测试覆盖率,两者都是必需的。 - Torsten Engelbrecht
11
这是如何检查特定表单错误的方法:self.assertEquals(form.errors['recipient'], [u"That recipient isn't valid"]) - Emil Stenström
19
self.assertEqual(form.is_valid(), True) 可以简化为 self.assertTrue(form.is_valid()) - Adam Taylor
显示剩余2条评论

87

这对我来说引发了一个AttibuteError: AttributeError: 'SafeUnicode'对象没有属性'errors'。 - sbaechler
对于新手用户:先创建一个用户,然后在测试方法的第一行使用 self.client.force_login(self.user) - sgauri
我之前在post()方法上遇到了问题,后来发现需要将数据以multipart的形式发送,代码如下:response = self.client.post("/form-url/", data={ 'name': 'test123', 'category': 1, 'note': 'note123' }, content_type=django.test.client.MULTIPART_CONTENT)如果在保存表单时出现空实例的情况,请检查浏览器发送的请求。 - Ghaleb Khaled
这个方法的签名在Django 4.1中已更改 - 使用response参数调用它已被弃用,并且在Django 5.0中将会失败。 - natka_m

19

原始答案为2011年

self.assertContains(response, "Invalid message here", 1, 200)

但是我现在看到(2018)有一大批可应用的断言可用

  • assertRaisesMessage
  • assertFieldOutput
  • assertFormError
  • assertFormsetError

任选其一。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接