Как я могу написать юнит-тест для проверки правильности формы модели Django? - PullRequest
2 голосов
/ 09 мая 2019

Я пытаюсь проверить правильность формы модели.

В тестовой функции я создаю две модели, которые представлены в моей пользовательской форме. Я добавляю данные, чтобы заполнить обязательные поля формы.

Когда я запускаю тесты и вызываю is_valid() в форме, тест завершается неудачно, и в форме выдается сообщение об ошибке, добавленная мной опция not one of the available choices. Это говорит о том, что я неправильно добавил экземпляр Option в форму или в тест. Я не уверен, как.

Как сделать форму модели действительной для теста?

tests.py

    def test_valid_data(self):
        question_1 = Question(
            question_text='What is the width of the telephone?',
            date_published=timezone.now(),
            collection=Collection.objects.create()
        )
        question_1.save()
        option_1 = question_1.options.create(
            question=question_1,
            option_text='Five centimetres'
        )
        option_1.save()
        data = {'question_text': question_1.question_text, 'selected_option': option_1.option_text,}
        form = QuestionForm(data=data)
        print(form)
        self.assertTrue(form.is_valid())

forms.py

class QuestionForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(QuestionForm, self).__init__(*args, **kwargs)
        self.fields['selected_option'] = forms.ChoiceField(
            choices=[
                (f'{option.pk}', f'{option}')
                for option in Option.objects.filter(question_id=self.instance.pk)
            ],
            widget=RadioSelect,
            required=True,
            error_messages={
                'required': 'The question form lacks a selected_option'
            }

        )

    class Meta:
        model = Question
        fields = ('question_text',)
        labels = {
            'question_text': ''
        }
        widgets = {
            'question_text': forms.Textarea(attrs={'cols': '40', 'rows': '2'})
        }

models.py

class Question(models.Model):
    question_text = models.CharField(max_length=400)
    collection = models.ForeignKey(Collection, on_delete=models.PROTECT, default=None)
    date_published = models.DateTimeField('date published')

    def __str__(self) -> str:
        return self.question_text


class Option(models.Model):
    option_text = models.CharField(max_length=400)
    question = models.ForeignKey(Question, on_delete=models.CASCADE)

    class Meta:
        default_related_name = 'options'

    def __str__(self) -> str:
        return self.option_text

Ожидаемое: is_valid() -> True

Факт: is_valid() -> False

1 Ответ

1 голос
/ 23 июня 2019

Проблема вызвана тем, что вы определили варианты в QuestionForm.__init__:

choices=[
    (f'{option.pk}', f'{option}')
    for option in Option.objects.filter(question_id=self.instance.pk)
],

Вы создали choices на основе pk экземпляра Question, связанного с QuestionForm, который вы инициируете.

В вашем тесте (а также в администраторе) form не связан ни с одним экземпляром Question, когда вы запускаете форму, вводя form = QuestionForm(data=data).

Следовательно, запрос Option.objects.filter(question_id=self.instance.pk) возвращает None, поскольку self.instance.pk равно None.

Поэтому перед сохранением QuestionForm появляется сообщение об ошибке, поскольку choices = []

Запрос вернет результаты, если вы нажмете кнопку «Сохранить» или если вы сделаете form.save().

...