Тестирование
Тестирование
Код без тестов сломан по умолчанию.
DRF включает несколько вспомогательных классов, которые расширяют существующую тестовую структуру Django и улучшают поддержку выполнения API-запросов.
APIRequestFactory
Расширяет существующий в Django класс RequestFactory
.
Создание тестовых запросов
Класс APIRequestFactory
поддерживает почти такой же API, как и стандартный класс Django RequestFactory
. Это означает, что все стандартные методы .get()
, .post()
, .put()
, .patch()
, .delete()
, .head()
и .options()
доступны.
Использование аргумента format
Методы, создающие тело запроса, такие как post
, put
и patch
, включают аргумент format
, что облегчает генерацию запросов, использующих тип содержимого, отличный от многокомпонентных данных формы. Например:
По умолчанию доступны форматы 'multipart'
и 'json'
. Для совместимости с существующей в Django RequestFactory
по умолчанию используется формат 'multipart'
.
Чтобы поддерживать более широкий набор форматов запросов или изменить формат по умолчанию, см. раздел конфигурации.
Явное кодирование тела запроса
Если вам нужно явно закодировать тело запроса, вы можете сделать это, установив флаг content_type
. Например:
PUT и PATCH с данными формы
Стоит отметить одно отличие между RequestFactory
Django и APIRequestFactory
DRF в том, что данные многочастной формы будут закодированы для методов, отличных от .post()
.
Например, используя APIRequestFactory
, вы можете сделать запрос формы PUT следующим образом:
Используя RequestFactory
от Django, вам придется явно кодировать данные самостоятельно:
Принудительная аутентификация
При тестировании представлений непосредственно с помощью фабрики запросов часто бывает удобно иметь возможность напрямую аутентифицировать запрос, а не создавать правильные учетные данные для аутентификации.
Чтобы принудительно аутентифицировать запрос, используйте метод force_authenticate()
.
Сигнатура для метода - force_authenticate(request, user=None, token=None)
. При выполнении вызова может быть задан пользователь и токен или оба.
Например, при принудительной аутентификации с помощью токена вы можете сделать что-то вроде следующего:
Примечание: force_authenticate
напрямую устанавливает request.user
в экземпляр user
в памяти. Если вы повторно используете один и тот же экземпляр user
в нескольких тестах, которые обновляют сохраненное состояние user
, вам может понадобиться вызывать refresh_from_db()
между тестами.
Примечание: При использовании APIRequestFactory
, возвращаемый объект - это стандартный HttpRequest
Django, а не объект Request
DRF, который генерируется только после вызова представления.
Это означает, что установка атрибутов непосредственно на объект запроса не всегда может иметь ожидаемый эффект. Например, установка .token
напрямую не будет иметь никакого эффекта, а установка .user
напрямую будет работать только при использовании сеансовой аутентификации.
Принудительная проверка CSRF
По умолчанию запросы, созданные с помощью APIRequestFactory
, не будут проходить проверку CSRF при передаче в представление DRF. Если вам необходимо явно включить проверку CSRF, вы можете сделать это, установив флаг enforce_csrf_checks
при инстанцировании фабрики.
Примечание: Стоит отметить, что стандартная фабрика запросов Django RequestFactory
не должна включать эту опцию, потому что при использовании обычного Django проверка CSRF происходит в промежуточном ПО, которое не запускается при тестировании представлений напрямую. При использовании DRF проверка CSRF происходит внутри представления, поэтому в фабрике запросов необходимо отключить проверку CSRF на уровне представления.
APIClient
Расширяет существующий в Django класс Client
.
Выполнение запросов
Класс APIClient
поддерживает тот же интерфейс запросов, что и стандартный класс Django Client
. Это означает, что стандартные методы .get()
, .post()
, .put()
, .patch()
, .delete()
, .head()
и .options()
доступны. Например:
Чтобы поддерживать более широкий набор форматов запросов или изменить формат по умолчанию, см. раздел конфигурации.
Аутентификация
.login(**kwargs)
Метод login
функционирует точно так же, как и в обычном классе Django Client
. Это позволяет вам аутентифицировать запросы к любым представлениям, которые включают SessionAuthentication
.
Чтобы выйти из системы, вызовите метод logout
, как обычно.
Метод login
подходит для тестирования API, использующих сеансовую аутентификацию, например, веб-сайтов, включающих AJAX-взаимодействие с API.
.credentials(**kwargs)
Метод credentials
можно использовать для установки заголовков, которые затем будут включены во все последующие запросы тестового клиента.
Обратите внимание, что вызов credentials
во второй раз перезаписывает все существующие учетные данные. Вы можете удалить все существующие учетные данные, вызвав метод без аргументов.
Метод credentials
подходит для тестирования API, требующих заголовков аутентификации, таких как базовая аутентификация, аутентификация OAuth1a и OAuth2, а также простые схемы аутентификации токенов.
.force_authenticate(user=None, token=None)
Иногда вы можете захотеть полностью обойти аутентификацию и заставить все запросы тестового клиента автоматически рассматриваться как аутентифицированные.
Это может быть полезным сокращением, если вы тестируете API, но не хотите создавать действительные учетные данные аутентификации для выполнения тестовых запросов.
Чтобы не аутентифицировать последующие запросы, вызовите force_authenticate
, установив для пользователя и/или токена значение None
.
Проверка CSRF
По умолчанию проверка CSRF не применяется при использовании APIClient
. Если вам необходимо явно включить проверку CSRF, вы можете сделать это, установив флаг enforce_csrf_checks
при инстанцировании клиента.
Обычно, проверка CSRF будет применяться только к любым аутентифицированным в сеансе представлениям. Это означает, что проверка CSRF будет происходить только в том случае, если клиент вошел в систему, вызвав login()
.
RequestsClient
DRF также включает клиент для взаимодействия с вашим приложением с помощью популярной библиотеки Python, requests
. Это может быть полезно, если:
Вы предполагаете взаимодействовать с API в основном из другого сервиса Python и хотите протестировать сервис на том же уровне, который будет видеть клиент.
Вы хотите написать тесты таким образом, чтобы их можно было запускать в среде постановки или в реальном времени. (См. раздел "Живые тесты" ниже).
Это предоставляет точно такой же интерфейс, как если бы вы использовали сессию запросов напрямую.
Обратите внимание, что клиент запросов требует передачи полностью определенных URL-адресов.
RequestsClient и работа с базой данных
Класс RequestsClient
полезен, если вы хотите написать тесты, которые взаимодействуют только с интерфейсом сервиса. Это немного строже, чем использование стандартного тестового клиента Django, поскольку это означает, что все взаимодействия должны осуществляться через API.
Если вы используете RequestsClient
, вам нужно убедиться, что установка тестов и утверждения результатов выполняются как обычные вызовы API, а не взаимодействуют с моделями базы данных напрямую. Например, вместо того чтобы проверять, что Customer.objects.count() == 3
, вы должны перечислить конечную точку customers
и убедиться, что она содержит три записи.
Заголовки и аутентификация
Пользовательские заголовки и учетные данные аутентификации могут быть предоставлены так же, как и при использовании стандартного экземпляра requests.Session
.
CSRF
Если вы используете SessionAuthentication
, то вам необходимо включить CSRF-токен для любых запросов POST
, PUT
, PATCH
или DELETE
.
Вы можете сделать это, следуя той же схеме, которую использует клиент на базе JavaScript. Сначала сделайте запрос GET
, чтобы получить маркер CSRF, а затем цкажите этот токен в следующем запросе.
Например...
Живые тесты
При тщательном использовании и RequestsClient
, и CoreAPIClient
дают возможность писать тесты, которые можно запускать как в процессе разработки, так и непосредственно на build сервере или в production среде.
Использование этого стиля для создания базовых тестов нескольких основных частей функциональности является мощным способом проверки вашего живого сервиса. Это может потребовать некоторого внимания к setup
и teardown
, чтобы убедиться, что тесты выполняются таким образом, что они не влияют непосредственно на данные клиентов.
CoreAPIClient
CoreAPIClient
позволяет вам взаимодействовать с API с помощью клиентской библиотеки Python coreapi
.
Заголовки и аутентификация
Пользовательские заголовки и аутентификация могут использоваться с CoreAPIClient
так же, как и с RequestsClient
.
Тесты API
DRF включает следующие классы тестов, которые являются зеркальным отражением существующих Django's test case classes, но используют APIClient
вместо Django's default Client
.
APISimpleTestCase
.APITransactionTestCase
APITestCase
APILiveServerTestCase
Пример
Вы можете использовать любой из классов тестов DRF так же, как и обычные классы тестов Django. Атрибутом self.client
будет экземпляр APIClient
.
URLPatternsTestCase
DRF также предоставляет класс тестов для изоляции urlpatterns
на основе каждого класса. Обратите внимание, что он наследуется от Django SimpleTestCase
, и, скорее всего, его придется смешивать с другим классом тестов.
Пример
Тестирование ответов
Проверка данных ответа
При проверке достоверности тестовых ответов часто удобнее проверять данные, на основе которых был создан ответ, чем проверять полностью отрисованный ответ.
Например, проще проверить response.data
:
Вместо того чтобы проверять результат разбора response.content
:
Ответы на рендеринг
Если вы тестируете представления напрямую, используя APIRequestFactory
, возвращаемые ответы еще не будут отрендерены, поскольку рендеринг ответов шаблона выполняется внутренним циклом запроса-ответа Django. Чтобы получить доступ к response.content
, вам сначала нужно отрендерить ответ.
Конфигурация
Установка формата по умолчанию
Формат по умолчанию, используемый для выполнения тестовых запросов, можно установить с помощью ключа настройки TEST_REQUEST_DEFAULT_FORMAT
. Например, чтобы всегда использовать JSON для тестовых запросов по умолчанию вместо стандартных multipart form запросов, установите следующее в файле settings.py
:
Установка доступных форматов
Если вам нужно протестировать запросы, использующие не многочастичные или json-запросы, вы можете сделать это, установив параметр TEST_REQUEST_RENDERER_CLASSES
.
Например, чтобы добавить поддержку использования format='html'
в тестовых запросах, в файле settings.py
можно сделать что-то вроде этого.
Last updated