[Python] Django views' tests return 403/200 code instead of (presumably) 302

Discussão em 'Python' iniciado por Stack, Março 9, 2025.

  1. Stack

    Stack Membro Participativo

    I'm testing views in my Django app. As the app is a backend of a forum site, I'm trying to test the creation, editing and deletion of a topic.

    Creation, editing and deletion of a topic are implemented in my app to work via redirect:

    • creation page (AddTopic) redirects to a succefully created topic's page;
    • editing the topic's initial comment (UpdateFirstComment) redirects from the editing page to the edited topic's page;
    • deletion page (DeleteTopic) redirects to a subforum (a chapter of a forum) where the deleted topic had belonged.

    I presume (I'm not sure; and, most possibly, here is my mistake) that the successful redirect code is 302, and in the tests' assertion that's the code which should be checked. But in practice, creation and editing tests return code 200, while the deletion test returns code 403. And I, due to the lack of experience, hardly can explain why it happens this way and how to deal with it.

    views.py:

    class TopicListView(FilterView):
    paginate_by = 20
    model = Topic
    template_name = "forum/subforum.html"
    slug_url_kwarg = 'subforum_slug'
    context_object_name = 'topics'
    filterset_class = TopicFilter

    def get_queryset(self):
    qs = self.model.objects.all()
    if self.kwargs.get('subforum_slug'):
    qs = qs.filter(subforum__slug=self.kwargs['subforum_slug'])
    return qs


    class ShowTopic(DetailView):
    model = Topic
    template_name = "forum/topic.html"
    slug_url_kwarg = 'topic_slug'
    context_object_name = 'topic'
    paginate_by = 5

    def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    topic = self.get_object()

    comments_list = Comment.objects.filter(topic=topic).order_by('created')
    paginator = Paginator(comments_list, self.paginate_by)
    page_number = self.request.GET.get('page', 1)
    page_obj = paginator.get_page(page_number)

    context.update({
    'menu': menu,
    'comments': page_obj,
    'page_obj': page_obj,
    'is_paginated': page_obj.has_other_pages(),
    'paginator': paginator,
    'comm_num': comments_list.count(),
    #'topic_rep': topic.total_rep,
    })

    return context


    class AddTopic(LoginRequiredMixin, CreateView):
    form_class = AddTopicForm
    template_name = 'forum/addtopic.html'
    page_title = 'Create new topic'

    def get_success_url(self):
    return reverse('forum:topic', kwargs={
    'subforum_slug': self.kwargs['subforum_slug'], 'topic_slug': self.object.slug})

    def form_valid(self, form):
    subforum = Subforum.objects.get(slug=self.kwargs['subforum_slug'])
    form.instance.creator = self.request.user
    form.instance.subforum = subforum
    return super(AddTopic, self).form_valid(form)


    class UpdateFirstComment(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    model = Topic
    form_class = AddTopicForm
    template_name = 'forum/editcomment.html'
    page_title = 'Edit topic'

    def test_func(self):
    topic = self.get_object()
    if self.request.user == topic.creator or self.request.user.is_superuser:
    return True
    return False

    def get_success_url(self):
    return reverse('forum:topic', kwargs={
    'subforum_slug': self.kwargs['subforum_slug'],
    'topic_slug': self.kwargs['topic_slug']
    })

    def get_object(self, queryset=None):
    return Topic.objects.get(slug=self.kwargs['topic_slug'], subforum__slug=self.kwargs['subforum_slug'])

    def form_valid(self, form):
    self.object = form.save(commit=False)
    first_comment = self.object.first_comment
    form.instance.creator = self.request.user
    form.instance.topic = self.object
    form.instance.first_comment = first_comment
    return super(UpdateFirstComment, self).form_valid(form)


    class DeleteTopic(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = Topic
    context_object_name = 'topic'
    template_name = 'forum/topic_confirm_delete.html'
    page_title = "Delete topic"
    fields = '__all__'

    def test_func(self):
    if self.request.user.is_superuser:
    return True
    return False

    def get_success_url(self):
    return reverse('forum:subforum', kwargs={'subforum_slug': self.kwargs['subforum_slug']})


    forum/urls.py (only for subforums and topics):

    <...>
    app_name = 'forum'

    urlpatterns = [
    path('', SubForumListView.as_view(), name='forum'),
    path('<slug:subforum_slug>/', TopicListView.as_view(), name='subforum'),
    path('<slug:subforum_slug>/add_topic/', AddTopic.as_view(), name="add_topic"),
    path('<slug:subforum_slug>/topics/<slug:topic_slug>/', ShowTopic.as_view(), name='topic'),
    path('<slug:subforum_slug>/topics/<slug:topic_slug>/edit_topic/', UpdateFirstComment.as_view(), name='edit_topic'),
    path('<slug:subforum_slug>/topics/<slug:topic_slug>/delete_topic/', DeleteTopic.as_view(), name='delete_topic'),
    ]


    tests.py (comments' section tests are omitted, they work fine):

    from django.test import TestCase
    from django.urls import reverse

    from . import factories, models
    from .models import Topic, Comment


    class SubforumTestCase(TestCase):
    def setUp(self):
    self.subforum = factories.SubForumFactory()
    self.user = factories.UserFactory()
    self.topic = factories.TopicFactory(subforum=self.subforum, creator=self.user)
    self.client.force_login(self.user)

    def test_get_topic_list(self):
    url = reverse('forum:subforum', kwargs={'subforum_slug': self.subforum.slug})
    response = self.client.get(url)

    self.assertEqual(response.status_code, 200)
    self.assertEqual(response.context['topics'].count(), models.Topic.objects.count())

    def test_get_topic_detail(self):
    url = reverse("forum:topic", kwargs={'subforum_slug': self.subforum.slug, 'topic_slug': self.topic.slug})
    response = self.client.get(url)

    self.assertEqual(response.status_code, 200)
    self.assertTemplateUsed(response, "forum/topic.html")

    def test_add_topic(self):
    data = {
    'subject': self.topic.subject,
    'first_comment': self.topic.first_comment
    }
    url = reverse("forum:add_topic", kwargs={'subforum_slug': self.subforum.slug})
    old_topics_count = Topic.objects.count()
    response = self.client.post(url, data=data)

    self.assertEqual(response.status_code, 302)
    self.assertEqual(Topic.objects.count(), 2)
    self.assertGreater(Topic.objects.count(), old_topics_count)

    def test_update_first_comment(self):
    data = {
    'first_comment': "Chebuldyk"
    }
    url = reverse("forum:edit_topic", kwargs={
    'subforum_slug': self.subforum.slug,
    'topic_slug': self.topic.slug
    })
    old_first_comment = self.topic.first_comment
    response = self.client.post(url, data=data)
    self.topic.refresh_from_db()

    self.assertEqual(response.status_code, 302)
    self.assertNotEqual(self.topic.first_comment, old_first_comment)

    def test_delete_topic(self):
    url = reverse("forum:delete_topic", kwargs={
    'subforum_slug': self.topic.subforum.slug,
    'topic_slug': self.topic.slug
    })
    old_topics_count = Topic.objects.count()
    response = self.client.delete(url)

    self.assertEqual(response.status_code, 302)
    self.assertGreater(old_topics_count, Topic.objects.count())


    results of testing:

    Found 8 test(s).
    Creating test database for alias 'default'...
    System check identified no issues (0 silenced).
    ...FF..F
    ======================================================================
    FAIL: test_add_topic (forum.tests.SubforumTestCase.test_add_topic)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
    File "D:\PyCharm Community Edition 2024.1.3\PycharmProjects\...\forum\tests.py", line 38, in test_add_topic
    self.assertEqual(response.status_code, 302)
    AssertionError: 200 != 302

    ======================================================================
    FAIL: test_delete_topic (forum.tests.SubforumTestCase.test_delete_topic)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
    File "D:\PyCharm Community Edition 2024.1.3\...\forum\tests.py", line 65, in test_delete_topic
    self.assertEqual(response.status_code, 302)
    AssertionError: 403 != 302

    ======================================================================
    FAIL: test_update_first_comment (forum.tests.SubforumTestCase.test_update_first_comment)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
    File "D:\PyCharm Community Edition 2024.1.3\PycharmProjects\...\forum\tests.py", line 54, in test_update_first_comment
    self.assertEqual(response.status_code, 302)
    AssertionError: 200 != 302

    ----------------------------------------------------------------------
    Ran 8 tests in 0.111s

    FAILED (failures=3)


    Tests work basing on factories; if necessary, I can provide them as well.

    Continue reading...

Compartilhe esta Página