Перевод статьи «API Testing Showdown: Postman vs Pytest. Part 1».
Когда речь заходит об автоматизации тестирования API, в ход идет множество инструментов. Фреймворк pytest в сочетании с библиотекой requests – один из самых популярных вариантов на сегодняшний день. В то же время у нас есть популярный HTTP-клиент для тестирования API – Postman. В нем даже присутствует функция написания автотестов – благодаря встроенному JS-движку.
Это первая часть нашего пособия. В ней мы рассмотрим, как вышеупомянутые инструменты справляются с тестами начального уровня, изучим систему переменных в Postman и порассуждаем о том, насколько этот клиент подходит в качестве IDE.
БЕСПЛАТНО СКАЧАТЬ КНИГИ в телеграм канале "Библиотека тестировщика"
Что такое Postman?
В синем углу ринга у нас расположился Postman. Это целая платформа для разработки API, содержащая множество функций.
![инструмент для тестирования API -Postman](https://qarocks.ru/wp-content/uploads/2023/12/image-67.png)
Postman позволяет проработать все необходимые части разработки API, включая документирование, создание прототипов и тестирование.
О последней части – тестировании – мы и поговорим.
Что такое Pytest?
В красном углу ринга находится Pytest – полнофункциональный фреймворк тестирования общего назначения на языке Python. В нем есть все, что только можно ожидать от такого типа инструментов: прогон тестов, метки, фикстуры, хуки и т.д. При этом он не является визуальным фреймворком.
“Из коробки” он подходит только для модульного тестирования. Чтобы сделать возможным тестирование REST API, нам необходимо то, что будет делать HTTP-запросы. Для этой цели будем использовать библиотеку Requests.
Небольшое замечание: далее по тексту мы будем обсуждать REST API, но те же принципы применимы и к другим протоколам.
Простой тест
Postman
Postman отлично подходит в качестве HTTP-клиента. Вам не нужно писать ни одной строки кода, чтобы увидеть ответ.
![создание запроса в Postman](https://qarocks.ru/wp-content/uploads/2023/12/image-68-1024x660.png)
Безусловно, вам придется написать код для создания ассертов (assert). Postman использует для этого движок JavaScript.
![пример автотеста в Postman](https://qarocks.ru/wp-content/uploads/2023/12/image-69-1024x660.png)
pm.test("Status code is 200", function () { pm.response.to.have.status(200); }); pm.test("2+2=4", function () { var jsonData = pm.response.json(); pm.expect(jsonData.sum).to.eql(4); });
Одна из примечательных особенностей этого инструмента – сниппеты кода. Этот небольшой тест был создан с их помощью.
![сниппеты в Postman](https://qarocks.ru/wp-content/uploads/2023/12/image-70.png)
Пара кликов + пара правок – и тест готов. Очень удобно для новичков!
Pytest
В Pytest все, что вам нужно, – это тестовая функция и стандартный оператор assert
Python (демо-версия приложения).
import requests from requests import codes def test_two_plus_two(): result = requests.post("http://127.0.0.1:8000/add", data={"a": 2, "b": 2}) assert result.status_code == codes.OK assert result.json()["sum"] == 4
Результаты тестов являются максимально полными сразу после установки, даже без каких-либо настроек.
![Результаты тестов](https://qarocks.ru/wp-content/uploads/2023/12/image-71-1024x684.png)
На этом этапе все хорошо. Простые тесты, быстрые решения. Postman выглядит лучше в качестве графического инструмента, и у него есть удобный раздел “Результаты тестов”. С другой стороны, код Pytest чище, чем код JS в Postman. Результаты тестов Postman визуально привлекательнее, в то время как результаты Pytest гораздо подробнее. Пока что явного победителя нет.
Но давайте поразмыслим на эту тему.
Не сравниваем ли мы несравнимое?
Нам нужно остановиться и подумать, насколько корректно такое сравнение. Разве мы не сравниваем совершенно разные категории, как, например, яблоки и лапшу?
С одной стороны, да. Postman – это API-клиент/платформа API, а Pytest – фреймворк для тестирования. Существует много вариантов использования, с которыми Postman может справиться, а Pytest – нет, и наоборот.
С другой стороны, оба инструмента можно использовать для автоматизированного тестирования API.
![сравнение Postman и Pytest](https://qarocks.ru/wp-content/uploads/2023/12/image-72-1024x734.png)
В общем, сравнивать их все же стоит, и вам, как инженеру по тестированию, придется выбрать что-то одно, если ваши автотесты будут сложными и серьезными.
Краеугольный камень
В действительности существует две причины возникновения проблем с автотестами в Postman:
- Postman, прежде всего, является клиентом API
- Основным объектом в Postman является запрос
Автотесты – это лишь дополнение к запросам Postman, а не их основа.
![Соотношение запросов и тестов в Postman](https://qarocks.ru/wp-content/uploads/2023/12/image-73-1024x637.png)
Хотя это может показаться тривиальным, такой подход довольно сложен для покрытия бизнес-потоков и поддержки автотестов. В дальнейшем вы увидите, как он может все усложнить.
В то же время полноценные фреймворки (в нашем случае Pytest) ставят тесты на первый план. Тест – это основа, а запрос может происходить внутри процедуры тестирования или настройки.
![Соотношение тестов и запросов с ассертами](https://qarocks.ru/wp-content/uploads/2023/12/image-74-1024x635.png)
Давайте углубимся в подход Postman к тестированию.
Отдельные скрипты
Существует множество скриптов, которые можно запускать до и после выполнения запроса. Эти скрипты определяются разными уровнями иерархии рабочей области Postman.
![порядок выполнения скриптов в Postman](https://qarocks.ru/wp-content/uploads/2023/12/image-75-1024x357.png)
![Древовидная структура: коллекция - папка - запрос/ответ](https://qarocks.ru/wp-content/uploads/2023/12/image-76-1024x367.png)
Скрипты хранятся в отдельных местах, что значительно усложняет работу с кодом.
![Три вкладки: запрос, папка, коллекция](https://qarocks.ru/wp-content/uploads/2023/12/image-77-1024x502.png)
В интерфейсе шесть подвкладок распределены между тремя вкладками. Эти вкладки не связаны в пользовательском интерфейсе напрямую. Поэтому, когда вы нажимаете кнопку “Отправить”, вы не можете сказать, что происходит в этой иерархии. Вам придется искать среди вкладок вручную. И все может стать еще сложнее, если мы будем использовать унаследованные папки…
![](https://qarocks.ru/wp-content/uploads/2023/12/image-78-1024x621.png)
…или попытаемся создать тестовый скрипт из нескольких запросов.
Что происходило с этой переменной?
Рассмотрим базовый CRUD.
![От запроса GET в CRUD отходит стрелка к тестовому скрипту](https://qarocks.ru/wp-content/uploads/2023/12/image-79-1024x365.png)
Предположим, у нас есть переменная new_world_name
, полученная из хранилища на уровне коллекции. В этом случае мы не можем сказать, когда была создана эта переменная и что происходило с ней на предыдущих шагах, не щелкнув предыдущие шаги и не просмотрев каждый пре-/постскрипт. А что, если мы захотим переименовать эту переменную?
А как насчет модулей Python?
“Папки и тестовые скрипты? Но ведь в Python все то же самое!” – могут сказать некоторые из вас. На самом деле, не совсем так. Модуль Pytest содержит тесты, а не запросы, со склеенными между собой скриптами. Вы можете легко увидеть, что происходит в тесте, не перескакивая с одного запроса на другой.
Предположим, ваш код распределен между несколькими модулями. В этом случае вы легко узнаете, как создается переменная и что происходит в тестовой настройке – благодаря заметному импорту и фикстурам в Pytest. Переименование переменных и рефакторинг кода в данном случае выглядит намного проще.
Области видимости и уровни переменных
Переменная в Postman может быть определена на нескольких уровнях.
![уровни определения переменной в Postman](https://qarocks.ru/wp-content/uploads/2023/12/image-3.jpeg)
Такая модель охвата соответствует духу Postman, но чревата рядом неудобств.
Локальные переменные
Допустим, у нас есть скрипт предзапроса (pre-request):
var company = 'Exness';
и последующий скрипт:
var message = 'Hello, ' + company; console.log(message);
Оправдано ли появление Hello, Exness в консоли Postman? Нет!
![](https://qarocks.ru/wp-content/uploads/2023/12/image-80-1024x424.png)
Проблема в том, что каждый скрипт запускается в отдельной песочнице, поэтому локальные переменные одного скрипта недоступны для другого. Чтобы поделиться чем-то, определенным в предзапросе, сохраните значение в области более высокого уровня. Например, в переменные коллекции.
Предварительный запрос:
var company = 'Exness'; pm.collectionVariables.set("company", company); // saving to collection variables
Тестовый скрипт:
var company = pm.collectionVariables.get("company") var message = 'Hello, ' + company; console.log(message);
Результат:
![В консоль выводится "Hello, Exness"](https://qarocks.ru/wp-content/uploads/2023/12/image-81-1024x381.png)
Довольно неудобно, не так ли? Посмотрим, как это может еще больше усложнить ситуацию.
Вы можете попробовать сделать это самостоятельно: коллекция.
Конечно, в Pytest такой проблемы нет. Ни в теле,
def test_variable_sharing(): company = "Exness" # define requests.get(...) logging.log(f"Hello, {company}") # reuse
ни в фикстурах:
@pytest.fixture def company(): company = "Exness" # define yield company # Pass to a test logging.log(f"Hello, {company}") # Teardown
Глобальные переменные тоже работают отлично.
company = "Exness" # define def test_1(): assert company == "Exness" # 1st usage def test_2(): assert len(company) == 6 # 2nd usage
У всех переменных тип данных – string
Один неприятный момент: в Postman все переменные на уровнях выше локального имеют тип данных string.
![Таблица с переменными и их начальными и текущими значениями](https://qarocks.ru/wp-content/uploads/2023/12/image-82-1024x417.png)
// saving collection variables as local ones var str_text = pm.collectionVariables.get("str"); var num_text = pm.collectionVariables.get("num"); var list_text = pm.collectionVariables.get("list"); var json_text = pm.collectionVariables.get("json"); // getting type of the variables and logging them console.log(typeof str_text); console.log(typeof num_text); console.log(typeof list_text); console.log(typeof json_text);
![В консоль выводятся типы переменных: все - "string"](https://qarocks.ru/wp-content/uploads/2023/12/image-83-1024x563.png)
Рассказываю, почему. Основное назначение переменных – вставка их в URL-адреса и заголовки. Но если вы хотите создать структуру, упрощающую рутинную работу, вы можете столкнуться с утомительным процессом многократного преобразования и анализа этих строк.
// saving collection variables as local ones var list_text = pm.collectionVariables.get("list"); console.log(typeof list_text); // parsing to get object var true_list = JSON.parse(list_text); console.log(typeof true_list); console.log(typeof true_list[0]); console.log(true_list);
![Вывод в консоль результатов парсинга get-объекта](https://qarocks.ru/wp-content/uploads/2023/12/image-84-1024x716.png)
Демо-коллекция находится здесь.
Отладка
Именно так мы должны производить отладку кода в Postman.
console.log(aaa); console.warn(bbb); console.error(ccc);
Помните красную точку останова, которая обычно используется для приостановки выполнения теста в вашей любимой IDE?
Забудьте о ней: разработчики Postman официально хотят, чтобы вы выполняли отладку через логирование переменных.
Надо отдать должное Postman, его журналы консоли впечатляют.
![Лог консоли](https://qarocks.ru/wp-content/uploads/2023/12/image-85-1024x600.png)
Но они все равно не могут заменить старые добрые точки останова.
Если вы все же надеетесь увидеть эту функцию в будущем, то я заранее вас разочарую. Песочница, которую использует Postman, запрещает реализацию этой возможности.
Сторонние IDE и редакторы кода
Можем ли мы использовать сторонние решения для имитации работы IDE?
Экспорт коллекций
Самый простой способ решить проблемы рефакторинга — экспортировать коллекцию.
![Экспорт коллекции](https://qarocks.ru/wp-content/uploads/2023/12/image-86-1024x503.png)
После этого вы можете использовать любой текстовый редактор, который вам нравится. Конечно, это не самый удобный способ работы с кодом.
![Этапы действий: экспорт коллекции, обновление кода, импорт коллекции назад](https://qarocks.ru/wp-content/uploads/2023/12/image-87-1024x166.png)
- Его трудно читать и легко сломать
- Нет кнопки “Запустить”
- Вам придется импортировать коллекцию назад и надеяться на лучшее после внесения изменений
- Вам придется каждый раз выполнять все вышеупомянутые действия по экспорту/импорту
Postman Local
Postman Local – это неофициальный инструмент, позволяющий производить различные манипуляции с коллекциями. Он загружает и выгружает коллекции через Postman API и хранит запросы и скрипты локально в папке, что существенно упрощает работу.
Плюсы:
- Код чище и разделен интуитивно, что гораздо лучше, чем необработанные экспортированные файлы.
- Вы можете вызывать код JS из любого места. Утилита автоматически добавит его в запросы. Конечно, это не обычный импорт JS, но это лучше, чем шаблонный код, который вы обычно распределяете по коллекциям.
Минусы:
- Точки останова отсутствуют.
- Кнопка запуска отсутствует. Вам все равно придется преобразовать отдельные файлы в коллекцию для последующего запуска.
- Переменные окружения Postman не интегрированы по умолчанию.
- Проект развивается медленно.
![График развития проекта postman-local: всплеск активности в январе 2020 года, затем небольшие подъемы до октября 2020 г и дальнейшая пустота](https://qarocks.ru/wp-content/uploads/2023/12/image-88-1024x633.png)
Я рекомендую попробовать Postman Local, если вы являетесь ярым поклонником Postman. Однако, по моему мнению, он не может заменить Pytest.
Модули и импорт
![Древовидная структура тестов в PyTest](https://qarocks.ru/wp-content/uploads/2023/12/image-89-1024x395.png)
Какая вещь есть (почти) в любом языке программирования? Импорт. Он позволяет нам повторно использовать старый код, сохраняя его чистоту. Вы всегда можете отследить, откуда этот класс и как была создана эта переменная. Есть ли у нас что-то подобное в Postman? Нет.
Расширение Postman VS Code
Когда я впервые увидел анонс, я подумал: “Ух ты, это, наверное, что-то новое!”. К сожалению, это не так. Это просто реализация обрезанного интерфейса Postman внутри VS Code.
![Расширение Postman VS Code](https://qarocks.ru/wp-content/uploads/2023/12/image-90-1024x576.png)
По сути это один и тот же инструмент. Он не может облегчить работу. Он даже может усложнить ее, так как многие функции здесь остались без внимания. Вероятно, в будущем появится возможность использовать больше IDE-вещей. Пока же Postman Local, созданный энтузиастами, выглядит гораздо более удобным и полезным.
Заключение
Оба инструмента, и Postman, и Pytest, подходят для простейшего автотестирования. Но когда вы начинаете писать код в Postman, вы сталкиваетесь с определенными трудностями. Одна из них – переменные. Вы не можете использовать локальную переменную в двух разных скриптах. Все переменные на уровнях выше локального имеют тип данных string. Это заставляет вас проходить через циклы сохранения-загрузки и загрузки-преобразования.
В следующей части мы рассмотрим, как можно реализовать процедуры установки/демонтажа в этих инструментах.