Структура адресов проекта Todo
В проекте Todo всего пять шаблонов URL.
Адреса приложения deals:
- главная страница
/
- список запланированных дел: страница
/task/
- вывод подробной информации о задаче: страница
/task/<slug:slug>/
- страница с сообщением об успешном добавлении задачи через форму: страница
/added/
Приложение staticpages управляет статическими информационными страницами. В проекте Todo создана лишь одна такая страница: /about/
.
Что тестировать в test_urls.py?
- Страницы доступны по ожидаемому адресу.
- Для страницы вызывается ожидаемый HTML-шаблон.
- Если у пользователя нет прав для просмотра страниц — они недоступны; происходит переадресация на ожидаемую целевую страницу.
Тестирование staticpages
Код приложения staticpages не просто лаконичный, а очень лаконичный. Протестировать его будет несложно.
# staticpages/urls.py
from django.urls import path
from .views import About
app_name = 'staticpages'
urlpatterns = [
path('', About.as_view(), name='about'),
]
Файлы для тестов приложения сохранены в директории staticpages/tests.
└── staticpages
├── __init__.py
├── tests
│ ├── __init__.py
│ ├── test_forms.py
│ ├── test_models.py
│ ├── test_views.py
│ └── test_urls.py # Тесты адресов
├── admin.py
├── forms.py
├── models.py
└── views.py
Тесты URL в staticpages
Страницы в staticpages доступны любому пользователю. Единственное, что можно проверить в при тестировании URL в этом приложении — что страница /about/
доступна по ожидаемому адресу.
Эта проверка может выглядеть так:
# staticpages/tests/test_urls.py
from django.test import TestCase, Client
class StaticPagesURLTests(TestCase):
def setUp(self):
# Создаем неавторизованый клиент
super().setUpClass()
self.guest_client = Client()
def test_about_url_exists_at_desired_location(self):
"""Проверка доступности адреса /page/about/."""
response = self.guest_client.get('/page/about/')
self.assertEqual(response.status_code, 200)
def def test_about_url_uses_correct_template(self):
"""Проверка шаблона для адреса /page/about/."""
response = self.guest_client.get('/page/about/')
self.assertTemplateUsed(response, 'staticpages/about.html')
В тесте создан клиент и проверяется, что при запросе к странице возвращается код 200. Примерно то же мы делали в smoke-тесте проекта Yatube.
Разумеется, если статических страниц будет больше одной, для их проверки хорошей идеей будет использовать subTests()
.
Тесты приложения deals
В проекте Todo создать новую задачу может любой посетитель, а просмотр списка задач и подробного описания каждой задачи доступно только авторизованным пользователям.Этими страницами управляет приложение deals. В нём нужно протестировать:
- доступность всех URL приложения для авторизованного пользователя;
- недоступность страниц
/task/
(список задач) и/task/<slug:slug>/
(полное описание отдельной задачи) для неавторизованного пользователя; - перенаправление неавторизованного пользователя на страницу логина при попытке зайти на страницы
/task/
и/task/<slug:slug>/
.
# deals/urls.py
from django.urls import path
from .views import Home, TaskList, TaskDetail, TaskAddSuccess
app_name = 'deals'
urlpatterns = [
path('', Home.as_view(), name='home'),
path('added/', TaskAddSuccess.as_view(), name='task_added'),
path('task/', TaskList.as_view(), name='task_list'),
path('task/<slug:slug>/', TaskDetail.as_view(), name='task_detail'),
]
Тестирование общедоступных страниц
Для начала через неавторизованный клиент протестируем доступность домашней страницы и страницы с сообщением об отправке формы.Первым делом — фикстуры в методе setUp()
:
from django.test import TestCase, Client
class TaskURLTests(TestCase):
def setUp(self):
# Создаем неавторизованный клиент
self.guest_client = Client()
)
# Проверяем общедоступные страницы
def test_home_url_exists_at_desired_location(self):
"""Страница / доступна любому пользователю."""
response = self.guest_client.get('/')
self.assertEqual(response.status_code, 200)
def test_task_added_url_exists_at_desired_location(self):
"""Страница /added/ доступна любому пользователю."""
response = self.guest_client.get('/added/')
self.assertEqual(response.status_code, 200)
Тесты доступности страниц для авторизованного пользователя и редиректов для неавторизованного
Для тестирования страниц task/
(полный список задач) и task/<slug:slug>/
(детальная информация об отдельной задаче) надо провести подготовку:
- создать запись в модели Task, в результате в проекте появится страница с описанием задачи
task/<slug:slug>/
; - создать запись в модели User — чтобы авторизовать клиент;
- создать веб-клиент с авторизованным пользователем.
from django.contrib.auth import get_user_model
from django.test import TestCase, Client
from deals.models import Task
User = get_user_model()
class TaskURLTests(TestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
# Создадим запись в БД для проверки доступности адреса task/test-slug/
Task.objects.create(
title='Тестовый заголовок',
text='Тестовый текст',
slug='test-slug'
)
def setUp(self):
# Создаем неавторизованный клиент
self.guest_client = Client()
# Создаем пользователя
self.user = User.objects.create_user(username='HasNoName')
# Создаем второй клиент
self.authorized_client = Client()
# Авторизуем пользователя
self.authorized_client.force_login(self.user)
def test_home_url_exists_at_desired_location(self):
"""Страница / доступна любому пользователю."""
response = self.guest_client.get('/')
self.assertEqual(response.status_code, 200)
def test_task_added_url_exists_at_desired_location(self):
"""Страница /added/ доступна любому пользователю."""
response = self.guest_client.get('/added/')
self.assertEqual(response.status_code, 200)
# Проверяем доступность страниц для авторизованного пользователя
def test_task_list_url_exists_at_desired_location(self):
"""Страница /task/ доступна авторизованному пользователю."""
response = self.authorized_client.get('/task/')
self.assertEqual(response.status_code, 200)
def test_task_detail_url_exists_at_desired_location_authorized(self):
"""Страница /task/test-slug/ доступна авторизованному
пользователю."""
response = self.authorized_client.get('/task/test-slug/')
self.assertEqual(response.status_code, 200)
# Проверяем редиректы для неавторизованного пользователя
def test_task_list_url_redirect_anonymous(self):
"""Страница /task/ перенаправляет анонимного пользователя."""
response = self.client.get('/task/')
self.assertEqual(response.status_code, 302)
def test_task_detail_url_redirect_anonymous(self):
"""Страница /task/test-slug/ перенаправляет анонимного
пользователя.
"""
response = self.client.get('/task/test-slug/')
self.assertEqual(response.status_code, 302)
В Django можно проверить предположение, что с определённого адреса происходит редирект на другую страницу: метод assertRedirects
позволяет одновременно протестировать
- статус ответа запрошенной страницы;
- статус ответа страницы, на которую ожидается редирект.
В функции test_unauthorized_user_newpage()
вместо метода assertEqual
лучше применить assertRedirects
:
# Проверяем редиректы для неавторизованного пользователя
def test_task_list_url_redirect_anonymous_on_admin_login(self):
"""Страница по адресу /task/ перенаправит анонимного
пользователя на страницу логина.
"""
response = self.guest_client.get('/task/', follow=True)
self.assertRedirects(
response, '/admin/login/?next=/task/'
)
def test_task_detail_url_redirect_anonymous_on_admin_login(self):
"""Страница по адресу /task/test_slug/ перенаправит анонимного
пользователя на страницу логина.
"""
response = self.client.get('/task/test-slug/', follow=True)
self.assertRedirects(
response, ('/admin/login/?next=/task/test-slug/'))
Проверка вызываемых HTML-шаблонов
from django.contrib.auth import get_user_model
from django.test import TestCase, Client
from deals.models import Task
User = get_user_model()
class TaskURLTests(TestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
# Создадим запись в БД для проверки доступности адреса task/test-slug/
Task.objects.create(
title='Тестовый заголовок',
text='Тестовый текст',
slug='test-slug'
)
def setUp(self):
# Создаем неавторизованный клиент
self.guest_client = Client()
# Создаем пользователя
self.user = User.objects.create_user(username='HasNoName')
# Создаем второй клиент
self.authorized_client = Client()
# Авторизуем пользователя
self.authorized_client.force_login(self.user)
# Проверка вызываемых шаблонов для каждого адреса
def test_home_url_uses_correct_template(self):
"""Страница по адресу / использует шаблон deals/home.html."""
response = self.authorized_client.get('/')
self.assertTemplateUsed(response, 'deals/home.html')
def test_added_url_uses_correct_template(self):
"""Страница /added/ использует шаблон deals/added.html."""
response = self.authorized_client.get('/added/')
self.assertTemplateUsed(response, 'deals/added.html')
def test_task_list_url_uses_correct_template(self):
"""Страница /task/ использует шаблон deals/task_list.html"""
response = self.authorized_client.get('/task/')
self.assertTemplateUsed(response, 'deals/task_list.html')
def test_task_detail_url_uses_correct_template(self):
"""Страница /task/test-slug/ использует
шаблон deals/task_detail.html.
"""
response = self.authorized_client.get('/task/test-slug/')
self.assertTemplateUsed(response, 'deals/task_detail.html')
Опять получилось слишком много однородных тестов. Через subTest()
будет лаконичнее и удобнее:
from django.contrib.auth import get_user_model
from django.test import TestCase, Client
from deals.models import Task
User = get_user_model()
class TaskURLTests(TestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
# Создадим запись в БД для проверки доступности адреса task/test-slug/
Task.objects.create(
title='Тестовый заголовок',
text='Тестовый текст',
slug='test-slug'
)
def setUp(self):
# Создаем неавторизованный клиент
self.guest_client = Client()
# Создаем пользователя
self.user = User.objects.create_user(username='HasNoName')
# Создаем второй клиент
self.authorized_client = Client()
# Авторизуем пользователя
self.authorized_client.force_login(self.user)
def test_urls_uses_correct_template(self):
"""URL-адрес использует соответствующий шаблон."""
# Шаблоны по адресам
templates_url_names = {
'deals/home.html': '/',
'deals/added.html': '/added/',
'deals/task_list.html': '/task/',
'deals/task_detail.html': '/task/test-slug/',
}
for template, adress in templates_url_names.items():
with self.subTest(adress=adress):
response = self.authorized_client.get(adress)
self.assertTemplateUsed(response, template)