带动态选择字段的测试表单

时间:2015-07-04 13:36:11

标签: python django unit-testing

我创建了一个包含TypedChoiceField的表单:

class EditProjectForm(ModelForm):
    def __init__(self, action, *args, **kwargs):
        super(EditProjectForm, self).__init__(*args, **kwargs)

        now = datetime.datetime.now()
        if action == 'edit':
            project_year = kwargs['project_year']
            self.fields['year'].choices = [(project_year, project_year)]
        else:
            self.fields['year'].choices = [(now.year, now.year), (now.year + 1, now.year + 1)]

    year = forms.TypedChoiceField(coerce=int)
    ...

在视图中使用它时,这非常适用。现在我想为这个表单编写测试:

form_params = {
    'project_year': datetime.datetime.now().year,
}
form = EditProjectForm('new', form_params)
self.assertTrue(form.is_valid())

测试失败,因为is_valid()返回False。这是因为在super.__init__()中调用EditProjectForm时,字段year尚未做出选择。因此,此字段的验证失败,并在表单内的错误列表中添加了错误。

super之后移动self.fields['year'].choices来电也不起作用,因为self.fields仅在super.__init__()来电后可用。

如何动态添加选项并仍能测试?

1 个答案:

答案 0 :(得分:0)

好的,我发现了问题。

字段year是一个类变量,甚至在测试setUp方法和表单__init__方法被调用之前就被实例化了。由于我没有为此字段传递所需的choices参数,因此error是在创建表单对象之前发出的。

我更改了行为,因此我更改了__init__方法中字段的类型,而不是使用类变量。

class EditProjectForm(ModelForm):
    def __init__(self, action, *args, **kwargs):
        super(EditProjectForm, self).__init__(*args, **kwargs)

        now = datetime.datetime.now()
        if action == 'edit':
            project_year = kwargs['project_year']
            choices = [(project_year, project_year)]
        else:
            choices = [(now.year, now.year), (now.year + 1, now.year + 1)]
        self.fields['year'] = forms.TypedChoiceField(coerce=int, choices=choices)