Ответ 1
NB NB! То, что я описываю ниже, не является строго "unit test"; почти невозможно записать независимый unit test для кода представления Django. Это скорее интеграционный тест...
Вы правы, что есть несколько путей в вашем представлении:
-
GET
илиPOST
анонимным пользователем (необходимо перенаправить на страницу входа) -
GET
илиPOST
зарегистрированным пользователем без профиля (должен поднять исключениеUserProfile.DoesNotExist
) -
GET
зарегистрированным пользователем (должен показать форму) -
POST
зарегистрированным пользователем с пустыми данными (должны отображаться ошибки формы) -
POST
зарегистрированным пользователем с недопустимыми данными (должны отображаться ошибки формы) -
POST
зарегистрированным пользователем с допустимыми данными (необходимо перенаправить)
Тестирование 1. действительно просто тестирует @login_required
, поэтому вы можете пропустить его. Я все равно тестирую его (на всякий случай я или кто-то еще забыл использовать этот декоратор).
Я не уверен, что случай сбоя (500 страниц ошибок) в 2. - это то, что вы действительно хотите. Я бы решил, что вы хотите вместо этого (возможно, использовать get_or_create()
или поймать исключение DoesNotExist
и создать новый профиль таким образом).
В зависимости от того, сколько пользовательских проверок у вас есть, 4. действительно не нужно тестировать.
В любом случае, учитывая все вышеизложенное, я бы сделал что-то вроде:
from django.test import TestCase
class TestCalls(TestCase):
def test_call_view_denies_anonymous(self):
response = self.client.get('/url/to/view', follow=True)
self.assertRedirects(response, '/login/')
response = self.client.post('/url/to/view', follow=True)
self.assertRedirects(response, '/login/')
def test_call_view_loads(self):
self.client.login(username='user', password='test') # defined in fixture or with factory in setUp()
response = self.client.get('/url/to/view')
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'conversation.html')
def test_call_view_fails_blank(self):
self.client.login(username='user', password='test')
response = self.client.post('/url/to/view', {}) # blank data dictionary
self.assertFormError(response, 'form', 'some_field', 'This field is required.')
# etc. ...
def test_call_view_fails_invalid(self):
# as above, but with invalid rather than blank data in dictionary
def test_call_view_fails_invalid(self):
# same again, but with valid data, then
self.assertRedirects(response, '/contact/1/calls/')
Очевидно, что недостатком здесь является жестко закодированные URL-адреса. Вы можете использовать reverse()
в своих тестах или создавать запросы, используя RequestFactory
и вызовите ваши представления как методы (а не по URL-адресу). Однако при последнем методе вам все равно нужно использовать жестко заданные значения или reverse()
для проверки целей перенаправления.
Надеюсь, что это поможет.