Функциональные тесты в Postman

| August 18, 2022

Введение

Postman - это целая платформа для построения и использования различных API. Это бесплатный инструмент, выросший из простейшего REST клиента до гигантского размера клубка различных фич.

В нём есть как возможности использования различных API, так и возможности проектирования и создания новых, возможности запланированного опрашивания разных сервисов на предмет их жизнеспособности (так называемые health check’и), создания mock серверов и так далее.

В этой небольшой статье, я бы хотел затронуть одну из функций Postman, которая могла бы пригодится каждому разработчику - тестирование API’ев. А так же, поделюсь идеями о внедрении этой функции в Ваши будни разработчика.

Основная часть

Отправной точкой в тестирование Ваших сервис являются Коллекции Postman. Коллекции Postman - это раздел Postman, в котором Вы можете группировать и организовать управление Запросами. Запросы организуются в папки и под-папки, согласно Вашему замыслу.

Рисунок 1. Пример организации коллекции

Настройки Запросов в Коллекциях находятся в специальных разделах. Из них, для нас представляют интерес ровно два - Pre-request Script и Tests.

Рисунок 2. Тестирование запросов

  • Pre-request Script - содержит в себе код сценария, написанный на JavaScript, который будет выполнен ДО выполнения самого запроса. Это может быть полезно тогда, когда для запроса существуют некоторые пред-условия или же для данного конкретного запроса нужно сохранить какую-либо информацию, которую можно будет использовать на этапе тестирования результатов.
  • Tests - содержит в себе код тестов, написанный на JavaScript. Код из этого раздела запускается после выполнения запроса и имеет доступ к ответу сервера.

Подопытный сервис

Достаточно теории. Переходим к практической части. Тесты пишутся для какого-то API. Поэтому для демонстрации создания тестов я буду использовать бесплатное публично API с сайта https://api.publicapis.org/entries.

Если просто перейти по ссылке выше, Вы сможете увидеть что именно вернёт наш GET запрос в Postman.

Создаём пред-условия

В разделе Pre-request Script мы можем описать сценарий, который будет выполнен до основного запроса. Какие это могут быть сценарии?

  1. Мы можем создать / запросить / организовать данные, необходимые для выполнения основного запроса
  2. Мы можем сохранить в переменные окружения наших тестов значения, которые могут понадобиться нам на этапе выполнения самих тестов. Хорошим примером данного подхода служит сохранение временной метки на момент вызова запроса, а затем, проверка временных меток в ответе сервера на предмет приближённости к тестовой.

На самом деле, возможности использования пред-условий не ограничены вышеназванными сценариями. Но, на мой взгляд, эти два - основные.

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

1425 - это магическое число и оно известно до выполнения запроса. Записать его в переменные окружения тестов можно следующим образом:

pm.environment.set('expected_count', 1425);

Пытливый читатель уже после этого кусочка кода может задать вопрос - а что такое этот pm? pm - это javascript объект, который доступен автору скриптов в Postman и именно с помощью этого объекта происходит работа с пред-условиями и тестами. Абсолютно всё, что мы можем делать в рамках наших тестов, делается через этот объект, поставляемый самим Postman.

Рисунок 3. pm объект

Создаём тесты

Теперь дело за малым - написать наши тесты. Прежде чем мы начнём разработку скрипта с тестом, неплохо было бы понять, а что именно мы будем тестировать. Нам нужен план тестирования.

Предлагаю протестировать следующие момента:

  1. Статус ответа сервера должен быть равен 200
  2. Переменная count в теле ответа должна иметь значение 1425 (ожидаемый результат)
  3. Количество элементов в массиве entries должно быть равно количеству, указанному в count
  4. И, наконец, все элементы массива entries должны иметь ссылки, использующие протокол https

Статус ответа сервера должен быть равен 200

Тесты пишутся в разделе Tests. Каждый новый тест описывается отдельной javascript функцией. Но чтобы сам Postman узнал о том, что конкретная функция является тестом, эту функцию мы должны передать Postman’у с помощью уже известной нам переменной pm. Делается это следующим образом:

pm.test('Response code must be equal 200', () => {
    pm.expect(pm.response.code).eql(200);
});

где

  • pm.test([Название теста], [Функция со сценарием теста]) - определение нового тестового сценария
  • pm.expect(pm.response.code).eql(200); - тело самого тестового сценария

Как уже было сказано выше, pm особенный объект, через интерфейс которого у нас есть доступ к запросам и ответам. Он так же позволяет писать assert’ы, с помощью функции expect. В примере выше, мы утверждаем, что статус ответа сервера должен быть 200.

Переменная count в теле ответа должна иметь значение 1425

Для реализации этого сценария, нам потребуется получить доступ к переменной окружения тестов, которую мы проинициализировали в разделе Pre-request Script. Полный код тестового сценария будет выглядеть следующим образом:

pm.test('Response \'count\' field must be equal to expected value', () => {
    var expectedCount = pm.environment.get('expected_count');
    var json = pm.response.json();
    pm.expect(json.count).eql(expectedCount);
});

где

  • pm.environment.get('expected_count') - доступ к заранее определённой в предусловиях переменной expected_count
  • var expectedCount = ... - объявление локальной переменной для удобства работы с данными
  • pm.response.json() - парсинг тела ответа сервера в json

Конструкция pm.expect(json.count).eql(expectedCount); уже должна быть Вам знакома из предыдущего раздела. Мы снова сравниваем два значения. Ничего нового.

Количество элементов в массиве entries должно быть равно количеству, указанному в count

Реализация этого сценария так же базируется на предыдущих элементах. Нам понадобиться получить json представление ответа сервера и получить размер массива entries. Выглядит это следующим образом:

pm.test('Response \'entries\' field must have expected size', () => {
    var json = pm.response.json();
    var count = json.count;
    var entriesCount = json.entries.length;
    pm.expect(count).eql(entriesCount);
});
  • var json = pm.response.json(); - получаем json представление тела ответа сервера
  • var count = json.count; - получаем значение поля count
  • var entriesCount = json.entries.length; - получаем значение размера массива entries. Напомню, по-скольку мы работаем с javascript, массивы javascript имеют свойство length, которое хранит его размер. Чем мы в данном примере и воспользовались
  • pm.expect(count).eql(entriesCount); - ну и наконец, ещё один assert

Все элементы массива entries должны иметь ссылки, использующие протокол https

Последний тестовый сценарий мы можем реализовать несколькими способами. Взглянем на данные в ответе сервера:

{
    "count": 1425,
    "entries": [
        {
            ...
            "HTTPS": true,
            ...
            "Link": "https://www.adoptapet.com/public/apis/pet_list.html",
            ...
        },

Мы можем организовать проверку одним из двух способов:

  • либо мы анализируем URL’ы на предмет используемого протокола,
  • либо, проверяем метаинформацию в поле HTTPS

Предлагаю пойти по простому пути и написать тестовый сценарий, который соответствует второму способу. Это будет выглядеть следующим образом:

pm.test('Response \'entries\' use https', () => {
    var json = pm.response.json();
    var nonSecuredEntries = json.entries.filter((el) => {
        return el.HTTPS == false;
    });
    pm.expect(nonSecuredEntries.length).eql(0);
})

где

  • var json = pm.response.json(); - получаем json тела ответа сервера
  • var nonSecuredEntries = json.entries.filter((el) => { return el.HTTPS == false; }); - фильтруем элементы массива entries по признаку HTTPS == false
  • pm.expect(nonSecuredEntries.length).eql(0); - ну и наконец проверяем, что наш массив entries не содержит ссылок, использующих не защищённый протокол

Вот как это выглядит в Postman: Рисунок 4. Полный текст тестового скрипта

Запускаем тесты

Чтобы выполнить наши тесты, достаточно выполнить сам запрос и результаты тестов будут отображены в разделе ответа сервера.

В нашем случае, это будет выглядеть следующим образом: Рисунок 5. Результаты выполнения тестов

Мы описали 4 тестовых сценария. Каждому из них дали собственное наименование. Именно эти 4 сценария, поимённо, выведены в результатах.

Мы так же видим, что последний сценарий не пройден. Там, где мы ожидали увидеть 0 элементов с http протоколом, нашлось аж 92 таких элемента. Тест резонно упал.

Функциональное тестирование

Тесты, которые мы составили, это обычные API тесты или функциональные тесты. Они оперируют API’ями на живых системах и являются простым способом организовать полу-автоматическую проверку работоспособности Ваших API’ев.

Почему полу-автоматическую? Потому что при текущем подходе, нам каждый раз нужно выполнять запуск выполнения запросов в Postman, для того, чтобы проверить работу тех или иных API.

А как этот процесс можно улучшить?

Для ответа на этот вопрос, у меня заготовлено два подхода.

Коллекция как набор тестов

Как уже было сказано выше, запросы в Postman можно группировать в папки и под-папки в коллекциях. Так почему бы не воспользоваться этим и не создать отдельные коллекции с тестовыми сценариями?

Пример: Рисунок 6. Функциональные тесты через Коллекции

На изображении выше, видно, что запросы в коллекции сгруппированы по сценариями. Есть некоторый гипотетический Audit Service, для которого мы проверяем 2 сценария - сценарий регистрации нового клиента и управления данными аудита.

При этом, Postman позволяет выполнять все запросы коллекции в заданном порядке, буквально, одним кликом. В меню каждой коллекции есть пункт - Run collection, нажатие на который и приводит к прогону абсолютно всех запросов и их тестов выбранной коллекции.

Рисунок 7. Запуск тестирования

Коллекция как автоматизированный набор тестов

В случае второго подхода, мы так же, оперируем коллекцией Postman, но - тесты прогоняем уже не сами, а, на каком-нибудь CI.

Есть такой прекрасный инструмент - Newman. Это инструмент командной строки, то есть, не имеет графического интерфейса пользователя (GUI) и позволяет запускать коллекции Postman.

Как, в этом случае, будет выглядеть процесс работы с тестами Postman?

  1. Разработчик тестов экспортирует коллекцию Postman во внешний файл (обычно это json со специальным содержимым)
  2. Добавляет полученный файл в репозиторий с тестами
  3. Для тестируемого приложения, на CI, создаётся отдельный шаг или отдельный план в котором выгружается из репозитория файл с тестами и передаётся на исполнение Newman

Заключительная часть

Я надеюсь после прочтения этой статьи Вы нашли для себя нечто новое и осознали, что Postman более не является простой API тыкалкой и пинговалкой.

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

Список материалов