Написание тестов для views.py

Что тестировать в views.py?

  1. Проверка контекста при формировании страниц
  2. Проверка работы модуля Paginator (разбиение постов на странице). Стандартный модуль Paginator раскладывает списки объектов по отдельным страницам и создаёт множество дополнительных инструментов для управления такими страницами.
  3. Проверка методов отображения URLs с соответствующими шаблонами.
  4. Различные элементы с редактированием страниц. Например появления поста, после его добавления.
Формирование класса для проверки Paginator

from django.contrib.auth import get_user_model
from django.test import Client, TestCase
from django.urls import reverse
from django.conf import settings
from django import forms

from ..models import Post, Group

TEST_OF_POST: int = 13
User = get_user_model()


class PaginatorViewsTest(TestCase):

    def setUp(self):
        self.guest_client = Client()
        self.user = User.objects.create_user(username='auth')
        self.authorized_client = Client()
        self.authorized_client.force_login(self.user)
        self.group = Group.objects.create(title='Тестовая группа',
                                          slug='test_group')
        bilk_post: list = []
        for i in range(TEST_OF_POST):
            bilk_post.append(Post(text=f'Тестовый текст {i}',
                                  group=self.group,
                                  author=self.user))
        Post.objects.bulk_create(bilk_post)
описание класса Paginator
Переменная TEST_OF_POST - отображает количество постов на странице.
В методе setUp заводятся два клиента: авторизованный и не авторизованный.
Создается тестовая группа group
Запускается цикл создания списка тестовых постов.
Вызывается метод bulk_create для создания всех постов в тестовой базе.
Проверка количества постов на первой и второй странице не авторизованного пользователя

   def test_correct_page_context_guest_client(self):
        '''Проверка количества постов на первой и второй страницах. '''
        pages: tuple = (reverse('posts:index'),
                        reverse('posts:profile',
                                kwargs={'username': f'{self.user.username}'}),
                        reverse('posts:group_list',
                                kwargs={'slug': f'{self.group.slug}'}))
        for page in pages:
            response1 = self.guest_client.get(page)
            response2 = self.guest_client.get(page + '?page=2')
            count_posts1 = len(response1.context['page_obj'])
            count_posts2 = len(response2.context['page_obj'])
            error_name1 = (f'Ошибка: {count_posts1} постов,'
                           f' должно {settings.FIRST_OF_POSTS}')
            error_name2 = (f'Ошибка: {count_posts2} постов,'
                           f'должно {TEST_OF_POST -settings.FIRST_OF_POSTS}')
            self.assertEqual(count_posts1,
                             settings.FIRST_OF_POSTS,
                             error_name1)
            self.assertEqual(count_posts2,
                             TEST_OF_POST - settings.FIRST_OF_POSTS,
                             error_name2)
описание метода test_correct_page_context_guest_client
1. Создается кортеж имен URL страниц, где используется Paginator.
2. Запускается цикл прохода по кортежу
3. получаем ссылки на объекты page. 1 и 2 "страница" Paginator'а от не авторизованного пользователя
4. Подсчитываем количество постов на странице
5. Формируем переменные ошибки на тесты
6. Проверяем методом assertEqual правильность отображения количества постов на "страницах"
Проверка количества постов на первой и второй странице авторизованного пользователя

    def test_correct_page_context_authorized_client(self):
        '''Проверка контекста страниц авторизованного пользователя'''
        pages = [reverse('posts:index'),
                 reverse('posts:profile',
                         kwargs={'username': f'{self.user.username}'}),
                 reverse('posts:group_list',
                         kwargs={'slug': f'{self.group.slug}'})]
        for page in pages:
            response1 = self.authorized_client.get(page)
            response2 = self.authorized_client.get(page + '?page=2')
            count_posts1 = len(response1.context['page_obj'])
            count_posts2 = len(response2.context['page_obj'])
            error_name1 = (f'Ошибка: {count_posts1} постов,'
                           f' должно {settings.FIRST_OF_POSTS}')
            error_name2 = (f'Ошибка: {count_posts2} постов,'
                           f'должно {TEST_OF_POST -settings.FIRST_OF_POSTS}')
            self.assertEqual(count_posts1,
                             settings.FIRST_OF_POSTS,
                             error_name1)
            self.assertEqual(count_posts2,
                             TEST_OF_POST - settings.FIRST_OF_POSTS,
                             error_name2)
описание метода test_correct_page_context_authorized_client
Проверка аналогичная. Отличие в обращении авторизованного пользователя self.authorized_client.get(page)

class ViewsTest(TestCase):

    def setUp(self):
        self.guest_client = Client()
        self.user = User.objects.create_user(username='auth')
        self.user2 = User.objects.create_user(username='auth2')
        self.authorized_client = Client()
        self.authorized_client.force_login(self.user)
        self.group = Group.objects.create(title='Тестовая группа',
                                          slug='test_group')
        self.post = Post.objects.create(text='Тестовый текст',
                                        group=self.group,
                                        author=self.user)

описание класса Viewstest
Создается отдельный класс проведения остальных тестов.
В нем указываются авторизованный и не авторизованный пользователь
Формируется тестовая группа и пост
Проверка URL-адрес использует соответствующий шаблон

def test_views_correct_template(self):
        '''URL-адрес использует соответствующий шаблон.'''
        templates_url_names = {
            reverse('posts:index'): 'posts/index.html',
            reverse('posts:group_list',
                    kwargs={'slug':
                            f'{self.group.slug}'}): 'posts/group_list.html',
            reverse('posts:profile',
                    kwargs={'username':
                            f'{self.user.username}'}): 'posts/profile.html',
            reverse('posts:post_detail',
                    kwargs={'post_id':
                            self.post.id}): 'posts/post_detail.html',
            reverse('posts:post_create'): 'posts/create_post.html',
            reverse('posts:post_edit',
                    kwargs={'post_id':
                            self.post.id}): 'posts/create_post.html'}
        for adress, template in templates_url_names.items():
            with self.subTest(adress=adress):
                response = self.authorized_client.get(adress)
                error_name = f'Ошибка: {adress} ожидал шаблон {template}'
                self.assertTemplateUsed(response, template, error_name)
описание метода test_views_correct_template
1. Формируется словарь с запросами страниц по указанным адресам URL и ответами на них.2
2. Запускается цикл проверки доступа авторизованного пользователя до указанных страниц методом assertTemplateUsed
Шаблон post_detail сформирован с правильным контекстом.

    def test_post_detail_page_show_correct_context(self):
        """Шаблон post_detail сформирован с правильным контекстом."""
        response = self.authorized_client.get(
            reverse('posts:post_detail', kwargs={'post_id': self.post.id}))
        post_text_0 = {response.context['post'].text: 'Тестовый пост',
                       response.context['post'].group: self.group,
                       response.context['post'].author: self.user.username}
        for value, expected in post_text_0.items():
            self.assertEqual(post_text_0[value], expected)
Описание метода test_post_detail_page_show_correct_context
1. Формируется запрос на создание поста
2. Заполняется словарь полями поста и итоговыми данными.
3. В цикле происходит сравнение ключей и значений словаря
Шаблон post_create сформирован с правильным контекстом.

def test_post_create_page_show_correct_context(self):
        """Шаблон post_create сформирован с правильным контекстом."""
        response = self.authorized_client.get(reverse('posts:post_create'))
        form_fields = {
            'text': forms.fields.CharField,
            'group': forms.fields.ChoiceField}
        for value, expected in form_fields.items():
            with self.subTest(value=value):
                form_field = response.context.get('form').fields.get(value)
                self.assertIsInstance(form_field, expected)
Описание метода test_post_create_page_show_correct_context
1. Формируется запрос на создание поста
2. Заполняется словарь полями поста и итоговыми данными.
3. В цикле происходит сравнение ключей и значений словаря
Пост при создании добавлен корректно

    def test_post_added_correctly(self):
        """Пост при создании добавлен корректно"""
        post = Post.objects.create(
            text='Тестовый текст проверка как добавился',
            author=self.user,
            group=self.group)
        response_index = self.authorized_client.get(
            reverse('posts:index'))
        response_group = self.authorized_client.get(
            reverse('posts:group_list',
                    kwargs={'slug': f'{self.group.slug}'}))
        response_profile = self.authorized_client.get(
            reverse('posts:profile',
                    kwargs={'username': f'{self.user.username}'}))
        index = response_index.context['page_obj']
        group = response_group.context['page_obj']
        profile = response_profile.context['page_obj']
        self.assertIn(post, index, 'поста нет на главной')
        self.assertIn(post, group, 'поста нет в профиле')
        self.assertIn(post, profile, 'поста нет в группе')
Описание метода test_post_create_page_show_correct_context
1. Создается пост
2. Формируется запрос поста со страниц: index, group_list, profile
3. Формируется запрос всех постов с определенных страниц
4. В цикле происходит сравнение входит ли пост в группу постов, полученных со страниц
Пост при создании не добавляется другому пользователю, но виден на главной и в группе

def test_post_added_correctly_user2(self):
        """Пост при создании не добавляется другому пользователю
           Но виден на главной и в группе"""
        group2 = Group.objects.create(title='Тестовая группа 2',
                                      slug='test_group2')
        posts_count = Post.objects.filter(group=self.group).count()
        post = Post.objects.create(
            text='Тестовый пост от другого автора',
            author=self.user2,
            group=group2)
        response_profile = self.authorized_client.get(
            reverse('posts:profile',
                    kwargs={'username': f'{self.user.username}'}))
        group = Post.objects.filter(group=self.group).count()
        profile = response_profile.context['page_obj']
        self.assertEqual(group, posts_count, 'поста нет в другой группе')
        self.assertNotIn(post, profile,
                         'поста нет в группе другого пользователя')
Описание метода test_post_added_correctly_user2
1. Создается вторая группа
2. Подсчитывается количество постов в 1 группе
3. Создается пост в группе 2 и от другого пользователя
4. Формируется запрос страницы profile.
5. Фильтруются посты группы 1 и подсчитывается их количество
6. Проверяется появился изменение количества постов assertEqual
7. Проверяется наличие поста у первого пользователя