Как подключить ответ GET-запроса django view к тому же представлению, что и POST-запрос во время тестирования? - PullRequest
0 голосов
/ 01 мая 2020

У меня есть Django функциональное представление формы, которое инициализирует форму с данными по умолчанию по запросу GET и сохраняет объект модели по запросу POST:

def copy(request, ann_id):
    new_ann = get_object_or_404(Announcement, pk=ann_id)
    new_ann.pk = None  # autogen a new primary key (quest_id by default)
    new_ann.title = "Copy of " + new_ann.title
    new_ann.draft = True
    new_ann.datetime_released = new_ann.datetime_released + timedelta(days=7)

    form = AnnouncementForm(request.POST or None, instance=new_ann)
    if form.is_valid():
        new_announcement = form.save(commit=False)
        new_announcement.author = request.user
        new_announcement.datetime_created = timezone.now()
        new_announcement.save()
        form.save()

        return redirect(new_announcement)

    context = {
        "title": "",
        "heading": "Copy an Announcement",
        "form": form,
        "submit_btn_value": "Create",
    }
    return render(request, "announcements/form.html", context)

Я не могу понять о том, как проверить ветку form.is_valid() при публикации формы, не предоставляя данные формы вручную для self.client.post(url, form_data), на мой взгляд.

Вот что я пытаюсь:

test_views.py

class AnnouncementViewTests(TestCase):

    def setUp(self):
        self.client = ...
        ... etc

    def test_copy_announcement(self):
        # log in a teacher
        success = self.client.login(username=self.test_teacher.username, password=self.test_password)
        self.assertTrue(success)

        # hit the view as a get request first, to load a copy of the announcement in the form
        response = self.client.get(
            reverse('announcements:copy', args=[self.test_announcement.id]),
        )
        self.assertEqual(response.status_code, 200)

        # The form in this response should be valid, and should bw
        # accepted on a post request, 
        # that is what I am testing in this integration test.

        form_data = response.how_do_get_the_form_data() # ???????

        response = self.client.post(
            reverse('announcements:copy', args=[self.test_announcement.id]),
            data=form_data
        )

        # Get the newest announcement just made in the post request
        new_ann = Announcement.objects.latest('datetime_created')

        self.assertRedirects(
            response, 
            new_ann.get_absolute_url()
        )

На самом деле я хочу проверить, что результат get предоставляет действительные данные по умолчанию для формы, которую затем можно отправить с помощью запроса post.

Но я не могу понять, как получить доступ к данным формы, полученным в результате запроса get, поэтому я могу затем передать их в form_data, предоставленные для запроса post.

РЕДАКТИРОВАТЬ

Я нашел расположение формы в ответе get, но я не знаю, как получить это в коде.

enter image description here

Ответы [ 3 ]

1 голос
/ 09 мая 2020

Вы можете получить доступ к форме ответа следующим образом:

response.context['form']

Отсюда вы можете построить свою полезную нагрузку следующим образом:

retrieved_instance = response.context['form'].instance
form_data = dict(title=retrieved_instance.title, ... <all the other fields>)
response = self.client.post(
            reverse('announcements:copy', args=[self.test_announcement.id]),
            data=form_data)
        )

Это не похоже на повторную отправку страницы, но очень похож, потому что вы повторно отправляете ту же форму.

На самом деле, ваш тест больше похож на тест e2e (если говорить об интеграции и e2e, то есть некоторая неоднозначность, скажем так), по этой причине, если бы я был Вы, я бы переключил «инструмент» и использовал бы селен для имитации взаимодействия с пользователем от начала (открытия существующего объявления) до конца, нажав кнопку «Отправить» на вашей веб-странице.

Только так вы отправляете «реальный» ответ «get»

Если вы новичок в этом виде теста, вы можете найдите здесь простое учебное пособие https://lincolnloop.com/blog/introduction-django-selenium-testing/, чтобы понять основные понятия.

1 голос
/ 06 мая 2020

Ваш вопрос немного сбивает с толку, но я постараюсь направить вас в правильном направлении.

Для очистки кода вы должны использовать Представление на основе классов , где вы можете легко использовать свою форму где угодно. Пример кода, который я только что написал:


class TestView(View):
    template_name = 'index.html'
    success_url = 'home' # dummy view
    context = {"form": myform()} 
    # myform is the definition/class of your form which contains all attrs.

    def get(self, request):
        context = self.context
        context['form'] = form # fill out your data here for get request
        return render(request, self.template_name, context)

    def post(self, request):
        context=self.context 
    # self.context certain that you're using exact form which you defined in class-scope
        form=context['form']
        # Form Validation
        if form.is_valid():
            #perform any logical validations here and save the form if required
        return redirect(self.success_url)

        context = self.context
        context['form'] = form # just to show you that you can access that form anywhere
        return render(request, self.template_name, context)
0 голосов
/ 06 мая 2020

Вы можете вручную передать данные в форму и проверить функцию is_valid в модульном тесте:

form_data = {'my': 'value', 'form': 'value', 'fields': 'value'}
form = AnnouncementForm(form_data)
self.assertFalse(form.is_valid)
...