测试时,如何将django视图GET请求的回复插入到同一个视图中作为POST请求?

问题描述 投票:0回答:1

我有一个基于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

django python-3.x django-forms django-testing
1个回答
1
投票

你可以用这种方式访问响应表单。

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的时候会有一些歧义,比方说),为此,如果我是你,我会切换 "工具",用selenium来模拟一个用户交互,从开始(打开一个现有的公告)到结束,按下网页上的提交按钮。

只有这样,你提交的才是 "真实 "的响应,"获取"

如果你对这种测试很陌生,你可以在这里找到一个简单的教程。https:/lincolnloop.comlogintroduction-django-selenium-testing。 来理解主要概念。


1
投票

你的问题有点混乱,但我会试着引导你走向正确的方向。

要清理代码,你应该使用 基于类的视图 在那里你可以很容易地在任何地方使用你的表格。我刚刚写了一个示例代码。


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
投票

你可以像这样手动传递数据到你的表单中,然后测试一下 is_valid 单元测试中的函数。

form_data = {'my': 'value', 'form': 'value', 'fields': 'value'}
form = AnnouncementForm(form_data)
self.assertFalse(form.is_valid)
© www.soinside.com 2019 - 2024. All rights reserved.