Написание тестов для urls.py
Что тестировать в urls.py?

  1. Страницы доступны по ожидаемому адресу.
  2. По адресу будет вызывается ожидаемый HTML-шаблон.
  3. Если у пользователя права для просмотра страниц ;
  4. Происходит ли переадресация на ожидаемую целевую страницу.
Прописанные пути в приложении статичных страниц urls.py
urlpatterns = [path('author/', views.AboutAuthorView.as_view(), name='author'),
               path('contact/', views.AboutContactView.as_view(), name='contact'),
               ]
Статичные страницы в приложениях Django предполагает, что все данные хранятся в шаблоне html и доступ к базе данных не осуществляется. В данном примере это страницы: "О авторе" и "Контакты"

Код статичных страниц на сайте тестируется просто.
Необходимо проверить несколько моментов:
  1. Страницы доступны по ожидаемому адресу.
  2. По адресу будет вызывается ожидаемый HTML-шаблон.
Предполагаем что доступ до подобных страниц открытый.

Отображения (views) страниц настроены просто. Они обращаются к страницам в папке templates в каталоге about
Тесты в файле test_urls.py
from http import HTTPStatus
from django.test import Client, TestCase


class StaticURLTests(TestCase):

    def setUp(self) -> None:
        self.guest_client = Client()
Что тестировать в urls.py?

  1. Импортируется класс HTTPStatus библиотеки http. Будем использовать Коды состояния HTTP для страницы
  2. Импортируется стандартные классы Django для тестирования и создания юзера.
  3. Определяется класс тестов, которые наследуется от класса TestCase;
  4. Вызывается метод setUp, в котором создается неавторизованный пользователь
Тест доступа страницы по URL
    def test_static_page(self) -> None:
        """Страница доступка по URL."""
        pages: tuple = ('/about/author/', '/about/tech/')
        for page in pages:
            response = self.guest_client.get(page)
            error_name: str = f'Ошибка: нет доступа до страницы {page}'
            self.assertEqual(response.status_code, HTTPStatus.OK, error_name)
Описание метода test_static_page

  1. Создается кортеж страниц для проверки доступа
  2. Описывается цикл прохождения по кортежу
  3. Формируется запрос пользователем страницы по указанному адресу
  4. Строка описания ошибки запроса страницы
  5. Проверка доступности страницы методом asserEqual. Сравнивается с состоянием доступа OK (200)
Проверка получения ожидаемых шаблонов по URL
    def test_urls_uses_correct_template(self) -> None:
        """URL-адрес использует соответствующий шаблон."""
        templates_url_names: dict = {
            '/about/author/': 'about/author.html',
            '/about/tech/': 'about/tech.html',
        }
        for adress, template in templates_url_names.items():
            with self.subTest(adress=adress):
                response = self.guest_client.get(adress)
                error_name: str = f'Ошибка: {adress} ожидал шаблон {template}'
                self.assertTemplateUsed(response, template, error_name)
Описание метода test_static_page

  1. Создается словарь страниц и ожидаемых страниц
  2. Описывается цикл прохождения по словарю
  3. В циклической проверке используется метод SubTest (метод subTest() устроен так, что при падении вложенного теста в отчёт будет выведено имя того поля, на котором упал тест)
  4. Формируется запрос пользователем страницы по указанному адресу
  5. Строка описания ошибки запроса страницы
  6. Проверка полученной страницы методом assertTemplateUsed.
Проверка не статичных страниц
Страницы в приложениях Django предполагает, формирование страницы с определенными данными из базы и разграничения доступа

Необходимо проверить:
1. доступность всех URL приложения для авторизованного пользователя (если групп несколько, то для каждой по отдельности);
2. недоступность определенных страниц для неавторизованного пользователя;
3. перенаправление неавторизованного пользователя на страницу логина при попытке зайти на запрещенные страницы или на страницу предупреждения.
    Также описываются вышеперечисленные тесты:

    1. Доступности страницы по адресу
    2. Получение ожидаемого шаблона страницы по адресу

    Возможно указать тест проверки получения недоступной страницы и получения в ответ Кода состояния HTTP.NOT_FOUND (404)
    Прописанные пути в приложении post страниц urls.py
    from django.urls import path
    from django.conf.urls import handler404, handler500
    
    from . import views
    
    
    handler404 = 'posts.views.error_404_view'
    handler500 = 'posts.views.error_500_view'
    
    app_name = 'posts'
    
    urlpatterns = [path('', views.index, name='index'),
                   path('group/<slug:slug>/', views.group_posts,
                        name='group_list'),
                   path('create/', views.post_create, name='post_create'),
                   path('posts/<int:post_id>/', views.post_detail,
                        name='post_detail'),
                   path('profile/<str:username>/', views.profile, name='profile'),
                   path('posts/<int:post_id>/edit/', views.post_edit,
                        name='post_edit'),
                   ]
    
    Описание путей

    1. Подключение библиотек для указание путей URL и страниц ошибок 404 и 500
    2. Переопределение отображений для переменных ошибок 404 и 500
    3. Определение области имен приложения app_name = 'posts'
    4. Формируется путей URL и элементов отображения URL
    Тесты в файле test_urls.py
    from django.contrib.auth import get_user_model
    from django.test import Client, TestCase
    from http import HTTPStatus
    
    from ..models import Group, Post
    
    User = get_user_model()
    
    
    class PostURLTests(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.post = Post.objects.create(
                author=self.user,
                text='Тестовое описание поста')
            self.group = Group.objects.create(
                title='Тестовая группа',
                slug='test_group',
                description='Тестовое описание')
    Формирование класса теста и метода setup

    1. Подключение библиотек для работы с тестами
    2. Подключения классов Group и Post для создания моделей поста и группы
    3. Создание двух пользователей (авторизованного и не авторизованного
    4. Создание тестового поста и группы
    Тест доступ неавторизованного пользователя
    def test_urls_guest_client(self):
            """Доступ неавторизованного пользователя"""
            pages: tuple = ('/',
                            f'/group/{self.group.slug}/',
                            f'/profile/{self.user.username}/',
                            f'/posts/{self.post.id}/')
            for page in pages:
                response = self.guest_client.get(page)
                error_name = f'Ошибка: нет доступа до страницы {page}'
                self.assertEqual(response.status_code, HTTPStatus.OK, error_name)
    ОПИСАНИЕ МЕТОДА test_urls_guest_client

    1. Подключение библиотек для работы с тестами
    2. Подключения классов Group и Post для создания моделей поста и группы
    3. Создание двух пользователей (авторизованного и не авторизованного
    4. Создание тестового поста и группы
    Тест редиректа неавторизованного пользователя
       def test_urls_redirect_guest_client(self):
            """Редирект неавторизованного пользователя"""
            url1 = '/auth/login/?next=/create/'
            url2 = f'/auth/login/?next=/posts/{self.post.id}/edit/'
            pages = {'/create/': url1,
                     f'/posts/{self.post.id}/edit/': url2}
            for page, value in pages.items():
                response = self.guest_client.get(page)
                self.assertRedirects(response, value)
    ОПИСАНИЕ МЕТОДА test_urls_redirect_guest_client
    Описаны пути на редирект пользователя. Пути формируются Django самостоятельно при указании редиректа в отображениях (views) по указанным путям. Вызов views указанно в файле urls.py, который описан выше. Пример post_create показан ниже.

    В тесте формируется словарь с указанными URL и адресами редиректа. В цикле проверяется редирект каждой страницы методом assertRedirects
    Пример "вьюхи" по запросу страницы /create/
    @login_required
    def post_create(request):
        template = 'posts/create_post.html'
        form = PostForm(request.POST or None)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.save()
            return redirect('posts:profile', request.user)
        return render(request, template, {'form': form})
    ОПИСАНИЕ МЕТОДА из файла views
    Декоратор @login_required - отвечает за проверку авторизованного пользователя и указывается у метода из views если он ограничен.
    Тест доступа авторизованного пользователя к ограниченным страницам
        def test_urls_authorized_client(self):
            """Доступ авторизованного пользователя"""
            pages: tuple = ('/create/',
                            f'/posts/{self.post.id}/edit/')
            for page in pages:
                response = self.authorized_client.get(page)
                error_name = f'Ошибка: нет доступа до страницы {page}'
                self.assertEqual(response.status_code, HTTPStatus.OK, error_name)
    ОПИСАНИЕ МЕТОДА TEST_URLS_REDIRECT_GUEST_CLIENT
    Формируется кортеж из страниц с ограниченным доступом и проверяется доступ до страниц методом assertEqual.
    Проверка получения ожидаемых шаблонов по URL
        def test_urls_uses_correct_template(self):
            """URL-адрес использует соответствующий шаблон."""
            templates_url_names: dict = {
                '/': 'posts/index.html',
                f'/group/{self.group.slug}/': 'posts/group_list.html',
                f'/profile/{self.user.username}/': 'posts/profile.html',
                f'/posts/{self.post.id}/': 'posts/post_detail.html',
                '/create/': 'posts/create_post.html',
                f'/posts/{self.post.id}/edit/': '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_urls_uses_correct_template
    1. Создается словарь страниц и ожидаемых страниц.
    2. Описывается цикл прохождения по словарю. В циклической проверке используется метод SubTest.
    3. Формируется запрос пользователем страницы по указанному адресу.
    4. Строка описания ошибки запроса страницы.
    5. Проверка полученной страницы методом assertTemplateUsed.