在POST请求中明确传递自填数据

时间:2015-07-06 11:20:32

标签: python django unit-testing testing

我想测试Update View的重定向。

阅读文档,查看源代码,我发现: 更新在处理请求之前查看实例self.object(这有助于将表单字段设置为当前值)

现在这是我想要的行为,但在测试期间给我带来了麻烦。

我的Models.py

class Project(models.Model):

    title = models.CharField(max_length=50)
    description = models.CharField(max_length=200, blank=True, default="")
    # Other fields

views.py

class UpdateProject(LogInRequiredMixin, UpdateView):

    form_class = ProjectUpdateForm
    template_name = 'project/create.html'

在测试中: (我创建了一个项目并在setUp中设置了大部分内容)

def test_redirection(self):
        # After updating project, users should land on correct page.[View Project page].
        self.client.login(username=self.owner.email, password=self.password)
        response = self.client.post(self.url, follow=True) # This will give error, since it requires Title field
        self.assertRedirects(response, reverse('project:show',
                                                kwargs={'project_id': self.project.id}))

现在,我知道我可以使用数据字段显式传递title,但是如果我稍后在模型中更改字段,那么这个测试也会失败,它不应该[它的唯一目的是检查重定向,那里是其他处理表单验证等的测试]

所以,我的问题是:有没有办法模拟Post View,就像更新视图一样(即通过将对象上下文设置为预填充值并仅覆盖更改的值来传递数据上下文)

2 个答案:

答案 0 :(得分:0)

该视图可能只是重定向成功。如果您没有传递足够的信息以使视图成功,那么它不应该重定向。所以听起来你想要一些不可能的东西 - 你想要测试代码在你正在设置的情况以外的情况下做了什么。

我的问题是:这个测试的价值是多少?为什么不把它放在检查成功的测试结束时呢?

我知道正常的测试口号是你只测试一件事,但我认为这对于这种情况来说是不切实际的,并且成本是脆弱的测试,它们破坏了某些内容。

另一种方法是你分开编写你的测试:

def _submit_good_form_data(self):
    response = self.client.post(self.url, follow=True, data={'title':'The title')

def test_form_success(self):
    response = self._submit_good_data()
    # asserts here 

def test_redirection(self):
    response = self._submit_good_data()
    # asserts here 

这样,当表单的性质发生变化时,您只有一个地方可以更新。

但是,我怀疑这是否真的值得,看到你正在大大增加测试运行的长度,它实际上并没有给你你真正追求的测试独立性(视图中的错误)会导致两个测试失败)。

答案 1 :(得分:0)

复制幕后机制的一种方法:

    get_response = self.client.get(self.url)
    response = self.client.post(self.url, data=get_response.context['object'].__dict__, follow=True)
    self.assertRedirects(response, reverse('project:show', kwargs={'project_id': self.project.id}))

不是很漂亮,但基本上是幕后的东西。