Создание тестов для REST API на Python с использованием запросов. Часть 4: имитация ответов |
15.10.2020 00:00 |
Автор: Баз Дейкстра (Bas Djikstra) В этой короткой серии статей я исследую библиотеку Python requests и ее использование для тестов REST API. Это четвертая статья в серии, и в ней мы разберемся с имитацией ответов для юнит-тестирования. Последние несколько месяцев я был занят улучшением своих навыков разработки. Сейчас я работаю над проектом на Python, и одна из моих задач как разработчика – это создание хороших юнит-тестов. Создавая эти тесты, я столкнулся с проблемой, пытаясь протестировать метод, включающий взаимодействие с REST API с использованием библиотеки requests. Естественно, я не хочу дергать сам API в моих юнит-тестах, поэтому я пытался найти способ имитации этой зависимости. Я рассматривал вариант создания имитаций с нуля, пока не наткнулся на библиотеку responses (PyPI, GitHub). Согласно их домашней странице, это "Полезная библиотека Python для имитации ответов на запросы". То, что доктор прописал. Итак, что же можно сделать с библиотекой responses, и как выгодно воспользоваться ей, создавая юнит-тесты? Давайте посмотрим на ряд примеров, имитирующих ответы для Zippopotam.us API. Создание имитации ответа Допустим, наш юнит-тест проверяет, что наш код реагирует на HTTP 404, возвращенный REST API, как полагается. Это подразумевает, что нам нужен способ "перекрыть" реальный ответ API при помощи ответа со статусом HTTP 404 и (возможно) с телом, в котором сидит сообщение об ошибке. Чтобы использовать библиотеку responses для имитации ответа, сначала надо добавить декоратор @responses.activate в тест-метод. Затем в тело тест-метода добавляется имитатор ответа: @responses.activate Когда вы используете библиотеку requests для выполнения HTTP GET-запроса к http://api.zippopotam.us/us/90210, то вместо ответа от живого API (со статусом 200) вы получите фальш-ответ, который можно проверить вот так: response = requests.get('http://api.zippopotam.us/us/90210') Таким образом можно добавлять любое количество имитаторов ответа. Неожиданные ответы Если в ходе тестирования вы случайно наткнетесь на конечную точку, к которой не привязан ни один имитатор ответа, вы получите ConnectionError: @responses.activate Симуляция исключений Если вы хотите проверить, как ваш код обращается с исключениями при вызове API при помощи requests, это тоже можно сделать с responses: @responses.activate Создание динамических ответов Если вы хотите сгенерировать более сложные и/или динамические ответы, это можно сделать, создав автоматический обратный вызов и используя его в имитации. Этот вызов должен возвращать кортеж, содержащий код статуса ответа (целое число), заголовки (словарь) и ответ (в формате строки). В этом примере я хочу интерпретировать URL запроса, взять оттуда параметры пути и использовать их в сообщении, которое я возвращаю в теле ответа: @responses.activate К тому же responses помнит все вызовы, сделанные автоматом, и все возвращенные ответы, и это очень полезно, если вы хотите убедиться, что ваш код сделал корректное количество вызовов: assert len(responses.calls) == 1 Самостоятельное использование примеров Примеры кода из статьи можно найти на моей страничке GitHub. Если вы скачали проект, то (если вы правильно установили Python) запустите: pip install -r requirements.txt из корневого каталога проекта python-requests для установки нужных библиотек, и вы сможете прогнать тесты самостоятельно. |