Почему результат тестирования с помощью Unittest в Джанго отличается от результата мануального теста в моём проекте?
Пишу тесты для проверки функции комментирования постов в проекте на Джанго.
При тестировании в ручном режиме происходит следующее:
- все пользователи могут просматривать пост, и видят форму для комментария.
- неавторизованный пользователь при нажатии кнопки "Отправить" под формой комментария перенаправляется на страницу авторизации. После авторизации он попадает обратно на страницу поста, где может видеть свой только что опубликованный комментарий.
Так и должно быть. Но Unittest
показывает, что после авторизации переадресация происходит на главную страницу.
class PostUrlTests(TestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.author = User.objects.create_user(username='author')
cls.creator = User.objects.create_user(username='creator')
cls.group = Group.objects.create(
title='Тестовая группа',
slug='test_slug',
description='Тестовое описание',
creator=cls.creator,
)
cls.post = Post.objects.create(
author=cls.author,
text='Тестовый не очень длинный пост',
group=cls.group
)
def setUp(self):
self.authorized_client_creator = Client()
self.authorized_client_creator.force_login(PostUrlTests.creator)
self.authorized_client_author = Client()
self.authorized_client_author.force_login(PostUrlTests.author)
def test_redirect_to_post_detail_after_login(self):
"""Пользователь перенаправляется на страницу поста после авторизации"""
self.user_with_password = User.objects.create_user(
username='user_with_password', password='password')
comment_text = 'Test comment after login'
post_detail_url = reverse('posts:post_detail', args=[self.post.id])
# Пытаемся оставить комментарий, будучи неавторизованным пользователем
response = self.client.post(post_detail_url, {'text': comment_text})
login_url = reverse('users:login')
expected_redirect_url = f'{login_url}?next={post_detail_url}'
self.assertRedirects(response, expected_redirect_url)
# Имитация логина через форму
login_response = self.client.post(
login_url,
{'username': 'user_with_password', 'password': 'password'}
)
# Проверяем, что после авторизации нас перенаправило на страницу поста
self.assertRedirects(login_response, post_detail_url)
# Проверяем, что комментарий успешно добавлен
self.assertTrue(Comment.objects.filter(
text=comment_text, post=self.post).exists())
Текст ошибки:
FAIL: test_redirect_to_post_detail_after_login (posts.tests.test_urls.PostUrlTests)
Пользователь перенаправляется на страницу поста после авторизации
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Dev\Yandex_Practicum\yatube_project\yatube\posts\tests\test_urls.py", line 97, in test_redirect_to_post_detail_after_login
self.assertRedirects(login_response, post_detail_url)
File "C:\Dev\Yandex_Practicum\yatube_project\venv\lib\site-packages\django\test\testcases.py", line 381, in assertRedirects
self.assertURLEqual(
File "C:\Dev\Yandex_Practicum\yatube_project\venv\lib\site-packages\django\test\testcases.py", line 401, in assertURLEqual
self.assertEqual(
AssertionError: '/' != '/posts/1/'
- /
+ /posts/1/
: Response redirected to '/', expected '/posts/1/'Expected '/' to
equal '/posts/1/'.
На всякий случай покажу код класса представления, но надеюсь, это не нужно, потому что он очень длинный:
class PostDetail(View):
def get(self, request, pk):
post = get_object_or_404(Post, pk=pk)
author = post.author
author_posts = Post.objects.filter(author=author)
post_count = author_posts.count()
comments = Comment.objects.filter(post=post)
form = CommentForm()
if (request.user.is_authenticated
and 'comment_form_data' in request.session):
form_data = request.session.pop('comment_form_data')
form = CommentForm(form_data)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.author = request.user
comment.save()
return redirect('posts:post_detail', pk=pk)
context = {
'post_count': post_count,
'post': post,
'author_posts': author_posts,
'comments': comments,
'form': form,
}
return render(request, 'posts/post_detail.html', context)
def post(self, request, pk):
post = get_object_or_404(Post, pk=pk)
form = self.get_comment_form(request)
if not request.user.is_authenticated:
return self.handle_unauthenticated_user(request)
form_data = request.session.pop('comment_form_data', request.POST)
form = CommentForm(form_data)
if 'comment_id' in form_data:
return self.edit_comment(request, form_data, pk)
if 'delete_comment_id' in request.POST:
return self.delete_comment(request, pk)
return self.add_or_render_comment(request, form, post, pk)
def get_comment_form(self, request):
return CommentForm(request.POST)
def handle_unauthenticated_user(self, request):
request.session['comment_form_data'] = request.POST
return redirect(f'{reverse("login")}?next={request.path}')
def edit_comment(self, request, form_data, pk):
comment_id = form_data['comment_id']
comment = get_object_or_404(Comment, pk=comment_id)
if comment.author != request.user:
return redirect('posts:post_detail', pk=pk)
form = CommentForm(form_data, instance=comment)
if form.is_valid():
form.save()
if request.is_ajax():
return JsonResponse({'text': comment.text})
return redirect('posts:post_detail', pk=pk)
def delete_comment(self, request, pk):
comment_id = request.POST['delete_comment_id']
comment = get_object_or_404(Comment, pk=comment_id)
if comment.author == request.user:
comment.delete()
return redirect('posts:post_detail', pk=pk)
def add_or_render_comment(self, request, form, post, pk):
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.author = request.user
comment.save()
if request.is_ajax():
return JsonResponse({
'id': comment.id,
'username': comment.author.username,
'text': comment.text,
'profile_url': reverse(
'posts:profile', args=[comment.author.username])
})
return redirect('posts:post_detail', pk=pk)
comments = Comment.objects.filter(post=post)
author_posts = Post.objects.filter(author=post.author)
post_count = author_posts.count()
context = {
'post_count': post_count,
'post': post,
'author_posts': author_posts,
'comments': comments,
'form': form,
}
return render(request, 'posts/post_detail.html', context)