Добрый День! Меня зовут Галактион, я – QA, в этой статье я собираюсь поделиться с Вами опытом автоматизации API посредством Postman, используя язык программирования - JavaScript.
Проект, о котором пойдет речь – это региональный портал государственных и муниципальных услуг, в котором интегрированы следующие сервисы (все перечислять не буду, т.к. их множество):

  • ЕМИАС (Единая медицинская информационно-аналитическая система), предназначенная для вызова и записи к врачу;

  • Запись в МФЦ;

  • Электронный дневник;

  • «ЕКЖИП» - Единая книга жалоб и предложений;

  • Платежи ГИБДД;

  • График отключения горячей воды и т.д.

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

Декомпозиция
Декомпозиция

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

Во вкладке Scripts необходимо извлечь токен с помощью простого скрипта и записать его в переменную глобального окружения или создать отдельное.

Генерация основного токена
Генерация основного токена
pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});

postman.setGlobalVariable("GeperidzeGO_token_prod", responseBody);

На первой и второй строках проверяем статус-код 200 от сервера. На пятой строке я прошу, чтобы тело ответа – “responseBody” записалось в переменную глобального окружения под названием “GeperidzeGO_token_prod”.
Snippets – это шаблоны, которые по умолчанию находятся под кнопкой “Send”. Каждый шаблон можете доработать под себя.

Шаблоны готовых скриптов
Шаблоны готовых скриптов

Далее необходимо перейти в раздел Environments – Globals, здесь записана переменная, которая будет хранить токен. Ps: Можете создать отдельное окружение.

Переменные глобального окружения
Переменные глобального окружения

В последующих запросах будем обращаться к глобальным переменным через двойные фигурные скобки «{{}}».
В запросы подставляем глобальную переменную в заголовок запроса по ключу авторизации

Обращение к токену
Обращение к токену

Предлагаю разобрать пример коллекции ЕМИАС – сервис записи к врачу. Для того, чтобы записаться к врачу, нам необходимо отправить следующие запросы.

Коллекция запросов сервиса
Коллекция запросов сервиса

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

Генерация токена интегратора
Генерация токена интегратора
var jsonData = JSON.parse(responseBody);
postman.setGlobalVariable("emias_token_***", jsonData.***);

pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});

В первой строке я ввожу переменную jsonData для парсинга тела ответа. JSON. parse() обрабатывает строку в формате JSON, при ошибке парсинга будет выведена ошибка, что был нарушен синтаксис. responseBody – тело ответа (целиком). В конце второй строки я заблюрил ключ, по которому ответ предоставляет токен. А обращаемся к ключу по имени нашей переменной и через точку пишем имя ключа, например, “jsonData.key”.

Далее отправляется запрос по конкретному врачу для получения открытых к записи дней недели (предварительно у меня выбрана специализация - хардкод, т.к. специализация тестовая).

Поиск первого свободного дня у первого подходящего врача
Поиск первого свободного дня у первого подходящего врача
console.log('Start test case');
pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});

console.log('Test case finished, try to set date');

var jsonData = JSON.parse(responseBody);

var items = jsonData.items[0];
var doctors = items.doctors;
for (var i = 0; i < doctors.length; i++) {
    var doctor = items.doctors[i];
    console.log('Processing doctor: ' + doctor.name);
    for (var j = 0; j < doctor.schedule.length; j++) {
        var sched = doctor.schedule[j];
        console.log('Processing schedule: ' + sched.date);
        if (sched.count_tickets > 0) {
            console.log('Find available day, trey to set global variable');
            postman.setGlobalVariable("available_date", sched.date.substr(0, 10));
            postman.setGlobalVariable("doctor_id", doctor.id)
            postman.setGlobalVariable("lpu_code", doctor.lpu_code)
            return;
        }
    }
}

В 10-ой строке я ввожу переменную items, где меня интересует первый открытый день для записи. В 11-ой строке я ввожу переменную doctors, для получения списка доступных врачей. В 12 строке я запускаю цикл, который проходит по каждому доступному врачу. Далее – на 15-ой строке я запускаю вложенный цикл, в котором хочу получить все расписания свободных дней для записи. На 18-ой строке я уточняю, есть ли наличие свободных талонов, если все условия выполняются, то я прошу записать данные в переменные глобального окружения.
Вложенный цикл используется потому, что массив тела ответа состоит из нескольких слоев.

Ответ по свободным дням
Ответ по свободным дням

В следующем запросе я получаю свободные талоны по конкретному дню и врачу.

Поиск первого свободного талончика
Поиск первого свободного талончика
pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});

var jsonData = JSON.parse(responseBody);

var schedule = jsonData.schedule;
for (var i = 0; i < schedule.length; i++){
        if (schedule[i].access == true){
            postman.setGlobalVariable("ticket_time", schedule[i].time)
        }
}

В 8-ой строке я запускаю цикл, по которому прошу найти доступную запись и записать ее в переменную “ticket_time”.

Далее мы отправляем POST-запрос для записи к врачу, в теле передаю необходимые переменные.

Запись к врачу, пост-запрос - тело
Запись к врачу, пост-запрос - тело

В этом же запросе я прошу получить айди записи к врачу для ее последующей отмены.

Запись к врачу, пост-запрос - скрипт
Запись к врачу, пост-запрос - скрипт
pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});

var jsonData = JSON.parse(responseBody);
postman.setGlobalVariable("doctor_entry_id", jsonData.entry_id);

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

Удаление записи
Удаление записи

Таким образом, весь сценарий состоит из 6 минимальных запросов. Скорость прогона данной папки – 5 секунд, в том случае, если проблем с сервером или подключением нет, а также отсутствуют раннее созданные записи. А если есть ошибки, то запросы будут отправляться и падать по тайм-аутам, которые устанавливают разработчики (как правило 30-60 секунд). В правилах хорошего тона - очищать за собой пространство от тестовых данных во избежание дубликатов или отсутствия возможности записаться, так как активная запись может быть только одна - повалятся ошибки 400 "Bad request".

Запуск коллекции. Тапаем по многоточию/мультивыбору, кому как нравится - тапаем по "Run folder". Ps: Аналогично прогоняется вся директория "Run collection". Ограничений у "Run folder" по количеству запусков нет, а у "Run collection" - 25 запусков/месяц - бесплатно.

Runner
Runner

Не забудьте поставить чек-бокс - для парсинга тел ответа.

Результат прогона
Результат прогона

API тесты более стабильные по сравнению с GUI – их легче писать и поддерживать. Такая коллекция сокращает время при регрессах, ее можно ставить на ежедневный прогон с помощью раздела Monitors.

Монитор
Монитор

Если Вы ручной тестировщик и планируете развиваться в авто – API-тесты могут стать Вашим первым шагом для миграции в AQA.
Один из минусов – прогон коллекций в бесплатной версии Postman ограничен до 25 ранов в месяц, поэтому при наличии времени коллекцию можно перенести в Python - используя фреймворк Pytest и библиотеку Requests, если планируете ежедневные запуски - введение CI.

Лимиты прогонов
Лимиты прогонов

Комментарии (3)


  1. pvzh
    05.09.2024 15:45
    +2

    В заголовке между «Автоматизация» и «REST API» пропало важное слово «тестирования». А вот слово «REST» не обязательное, там не только HTTP. Постман это же привязка к иностранному облаку, уже вроде наелись такого. Есть же более свободный httpYac.


  1. Rubilnik
    05.09.2024 15:45

    прогон коллекций в бесплатной версии Postman ограничен до 25 ранов в месяц

    Могу ошибаться, но вроде как если локально поставить postman - ограничений нет на прогоны...


  1. dskonev
    05.09.2024 15:45

    Простите за душноту, но что значит "Я - QA"? QA - это уверенность в качестве. Ну или процесс обеспечения качества. QA - это не человек.