Разделы портала

Онлайн-тренинги

.
Создание тестов для REST API на Python с использованием запросов. Часть 1: базовые тесты
14.04.2020 00:00

Автор: Баз Дейкстра (Bas Djikstra)
Оригинал статьи
Перевод: Ольга Алифанова

В этой короткой серии статей я хочу исследовать библиотеку запросов Python и то, как ее можно использовать для создания тестов REST API. Это первая статья, и она посвящена тому, как начать и написать первые тесты для выборочного REST API.

Как начать

Для начала нам понадобится свежая установка интерпретатора Python, который можно скачать здесь. Затем нужно создать новый проект в IDE (я использую PyCharm, но сойдет любая приличная IDE) и установить библиотеку запросов. Проще всего использовать pip, менеджер пакетов Python:

pip install -U requests

Нам также понадобится фреймворк юнит-тестирования для запуска тестов, библиотеки утверждения и базовой функциональности отчетов. Я предпочитаю pytest, но запросы так же хорошо работают с любым другим фреймворком юнит-тестирования Python.

  1. import requests

Тестируемое API

Для примеров в этой статье я буду использовать REST API Zippopotam.us. Этот API берет код страны и индекс, и возвращает данные о геолокации, соответствующей этой стране и индексу. К примеру, GET-запрос к http://api.zippopotam.us/us/90210 вернет код HTTP-статуса 200 и вот такое тело ответа JSON:

  1. {
  2. "post code": "90210",
  3. "country": "United States",
  4. "country abbreviation": "US",
  5. "places": [
  6. {
  7. "place name": "Beverly Hills",
  8. "longitude": "-118.4065",
  9. "state": "California",
  10. "state abbreviation": "CA",
  11. "latitude": "34.0901"
  12. }
  13. ]
  14. }

Первый тест с использованием запросов и pytest

В качестве первого теста воспользуемся библиотекой запросов, чтобы вызвать вышеуказанный эндпойнт API и написать утверждение, проверяющее, что код HTTP-статуса равен 200:

  1. def test_get_locations_for_us_90210_check_status_code_equals_200():
  2. response = requests.get("http://api.zippopotam.us/us/90210")
  3. assert response.status_code == 200

Что тут происходит? В первой строчке теста мы вызываем метод get() из библиотеки запросов, чтобы выполнить запрос HTTP GET к определенной конечной точке, и сохраняем полный ответ в переменной response. Затем мы получаем свойство status_code из объекта ответа и пишем утверждение, используя ключевое слово pytest – assert, - проверяющее, что код статуса равен 200, как и ожидалось.

Вот и все о первом, и, конечно, очень простеньком тесте нашего API. Запустим этот тест и посмотрим, что будет. Я предпочитаю пользоваться командной строкой, потому что именно так мы будем запускать тесты, когда они станут частью автоматизированного процесса сборки. Мы можем сделать это, вызвав pytest и сообщив ему, где искать файлы тестов. Используя проект, ссылка на который дана в конце статьи, и предполагая, что мы находимся в корневой папке проекта, вызов

pytest tests\01_basic_tests.py

Даст в результате такую информацию в консоли:

 

Кажется, наш тест пройден. Так как я не доверяю тестам, падения которых не видел (и вам не советую), давайте изменим ожидаемый HTTP-код статуса с 200 на 201 и посмотрим, что будет.

 

Это изменение, как можно видеть, заставило тест упасть. Кажется, с этим тестом все в порядке.

Расширение тестового набора

Как правило, нас интересует не только HTTP-код статуса ответа. К примеру, давайте проверим, правильно ли значение заголовка Content Type идентифицирует тело ответа как формат JSON:

That makes our test fail, as you can see. It looks like we’re good to go with this one.

  1. def test_get_locations_for_us_90210_check_content_type_equals_json():
  2. response = requests.get("http://api.zippopotam.us/us/90210")
  3. assert response.headers['Content-Type'] == "application/json"

В объекте ответа заголовки доступны как словарь (список пар ключ-значение) headers, и получить значение определенного заголовка можно, передав правильный ключ (имя заголовка). Затем мы можем проверить полученное значение, используя утверждение pytest и ожидаемое значение ‘application/json‘.

Как насчет проверки элементов тела ответа? Давайте вначале убедимся, что элемент тела ответа country (см. пример ответа JSON выше) соответствует стране United States:

  1. def test_get_locations_for_us_90210_check_country_equals_united_states():
  2. response = requests.get("http://api.zippopotam.us/us/90210")
  3. response_body = response.json()
  4. assert response_body["country"] == "United States"

Библиотека запросов поставляется со встроенным декодером JSON, которым можно пользоваться для получения тела ответа из объекта ответа и превращения его в настоящий JSON-объект. Декодер вызывается методом json(), который вернет ошибку ValueError, если тела ответа не существует, или в нем невалидный JSON.

После того, как мы трансформировали тело ответа в объект JSON, мы можем получить доступ к элементам тела, обращаясь к их имени – в этом случае country.

Для извлечения и проверки значения имени места для первого места в списке можно сделать что-то вроде этого:

  1. def test_get_locations_for_us_90210_check_city_equals_beverly_hills():
  2. response = requests.get("http://api.zippopotam.us/us/90210")
  3. response_body = response.json()
  4. assert response_body["places"][0]["place name"] == "Beverly Hills"

Последний пример – давайте проверим, что список мест, возвращенных API, содержит ровно одну запись:

  1. def test_get_locations_for_us_90210_check_one_place_is_returned():
  2. response = requests.get("http://api.zippopotam.us/us/90210")
  3. response_body = response.json()
  4. assert len(response_body["places"]) == 1

После конвертации тела ответа в JSON все это довольно просто. Метод len(), встроенный в Python, возвращает длину списка, в этом случае – количество элементов в массиве places в возвращенном API документе JSON.

В следующий раз мы рассмотрим создание управляемых тестов с использованием запросов и pytest.

Использование примеров

Примеры кода, использованного в статье, можно найти на моей странице GitHub. Скачав проект, запустите следующее (если вы правильно установили Python):

pip install -r requirements.txt

из корня проекта python-requests для установки нужных библиотек, и вы сможете запустить тесты самостоятельно.

Обсудить в форуме