Создание тестов для REST API на Python с использованием запросов. Часть 3: работа с XML |
24.07.2020 00:00 |
Автор: Баз Дейкстра (Bas Djikstra) Недавно я провел свой первый трехдневный курс "Python для тестировщиков". В нем я, в частности, раскрывал тему создания тестов REST API с использованием Python-библиотеки requests и фреймворка pytest для юнит-тестирования. В этой короткой серии статей я хочу показать, как можно использовать Python-библиотеку запросов для создания тестов REST API. Это третья часть серии, и в ней мы рассмотрим работу с XML-телами запросов и ответов. В предыдущих частях рассказывалось, как приступить к работе с requests и pytest, а также о создании тестов, управляемых через данные. REST API и XML Большинство REST API, с которыми я нынче сталкиваюсь, работают с JSON в качестве предпочтительного формата данных для тел запросов и ответов. Однако время от времени вы будете встречаться с API, работающими с XML. Так как с XML, по сравнению с JSON, немного труднее работать в коде (не только в Python, а в целом), я решил, что будет неплохой идеей показать примеры создания тел запросов XML и разобраться, как парсить и создавать тесты для XML-тел ответов, работая с библиотекой requests. Для примеров в статье я использовал операцию из REST API ParaBank, которая передает оплату счетов. Она доступна по адресу и включает, помимо двух параметров запроса, уточняющих источник (accountId) и сумму счета (amount), XML-тело запроса, содержащее информацию о человеке, которому отправляется платеж – то есть payee. Неудивительно, что тело запроса передается в API через HTTP POST. Создание XML-тела запроса с использованием строкЯ хочу показать вам два разных подхода к созданию XML-тел запросов. Первый наиболее прямолинеен, но также и наименее гибок: это создание метода, возвращающего строку, содержащую тело XML.
Заметьте, что двойные кавычки используются трижды, чтобы позволить вам объявить многострочную строку. Конечно, мы можем также читать тело из XML или текстового файла, который хранится в системе, вместо того, чтобы жестко кодировать его. Результат будет тем же. Если нужно передать это XML-тело запроса в API, это можно сделать так:
Отметьте, что мы явно указываем заголовок запроса Content-Type как application/xml, чтобы убедиться, что получатель понимает, что тело запроса должно интерпретироваться как XML. Отправка тела запроса XML происходит следующим образом: значение XML-строки, которую возвращает метод, приписывается параметру data метода requests post(). Чтобы проверить, что запрос успешно получен и обработан, мы убеждаемся, что код ответа 200, а заголовок ответа Content-Type имеет значение application/xml. С XML-телом ответа мы разберемся чуть позже. Создание XML-тела запроса с использованием ElementTreeДругой подход к работе с XML-телом запроса – это их программное построение. В Python для этого есть мощная библиотека, ElementTree. Мы можем импортировать ее в наш модуль:
Так как XML-документ – это по сути дерево с корневым узлом, к которому крепятся дочерние узлы, мы начинаем создавать тело XML-запроса, определяя корневой узел payee:
Затем мы определяем элемент name – дочерний элемент payee:
Нам также нужно назначить значение элемента name:
Для примера это не требуется, но если вам нужно добавить атрибут (например, type) со значением fullName к элементу name, вы можете сделать это так:
Создание полного XML-тела запроса для нашего API-вызова заключается в повторе этих строк в правильном порядке с правильными значениями:
Заметьте, что нам нужно сконвертировать дерево элементов в строку, прежде чем использовать его с библиотекой requests. Это можно сделать при помощи метода tostring(). Подход ElementTree может выглядеть чуть более замороченным, чем простое определение XML как строки, однако он дает возможность создавать более сложные и гибкие XML-документы при помощи циклов, повторяющих блоки XML, работы с источниками данных, которые трансформируются в XML, и так далее. У меня нет четкого предпочтения в подходах, однако я считаю, что нужно знать об обоих вариантах и выбирать тот, который лучше подходит для ваших требований. Чтобы использовать XML, созданный при помощи ElementTree, в качестве тела запроса, мы можем воспользоваться тем же способом, что и при создании строки, содержащей XML:
Интерпретация и работа с XML-телом ответаТеперь, когда мы разобрались с созданием XML-тел запроса, давайте посмотрим, что можно сделать с XML-ответами. На данный момент самым мощным способом создания конкретных тестов будет конвертация XML-тела ответа в ElementTree, а затем – проверка его свойств. В качестве примера выполним HTTP GET-вызов. Ответ вернет детали учетной записи с ID 12345. Если мы хотим проверить, скажем, то, что корневой узел XML-ответа имеет имя account, и что у него отсутствуют свойства и текстовое значение, это можно сделать так:
Заметьте, что сначала нам нужно сконвертировать XML-тело ответа в объект с типом Element, используя метод fromstring(), а затем – создать из этого ElementTree, используя конструктор ElementTree(), который принимает Element как аргумент. Если нас интересует текстовое значение конкретного дочернего элемента XML-ответа – к примеру, customerId, содержащего ID пользователя, которому принадлежит аккаунт, это можно сделать через поиск элемента в ElementTree при помощи метода find() и последующего создания проверки свойства text у этого элемента:
Метод find() возвращает первое упоминание об этом элементе. Если нам нужно получить все элементы, совпадающие с этим именем, нужно использовать findall():
Как можно видеть, вместо передачи имен элементов напрямую можно воспользоваться выражениями XPath для более сложного выбора. Выражение .//account/type[.='SAVINGS'] в примере выше выбирает все упоминания элемента type (дочернего элемента account), значение которых соответствует SAVINGS. Использование примеров Примеры кода из этой статьи можно найти на моей странице GitHub. Если вы скачаете проект и (при условии, что вы верно установили Python) запустите: in the example above selects all occurrences of the type element (a child element of account) that have SAVINGS as their element value. pip install -r requirements.txt из корня проекта python-requests для установки нужных библиотек, вы сможете прогнать тесты самостоятельно. |