Если вы работаете с API и вам надоело вручную протыкивать запросы в Postman, сталкиваться с платными ограничениями и невозможностью нормально делиться коллекциями с командой — вы не одиноки. Хватит это терпеть!
Именно с этими проблемами я столкнулся как системный аналитик в банке. Postman оказался неудобным, закрытым и дорогим инструментом для командной работы. Это заставило меня искать альтернативу, и я нашёл её в бесплатном и открытом API-клиенте Bruno.
В этой статье расскажу, как с ним работать и какие сценарии он закрывает в реальной проектной работе.
Кратко о том, почему я отказался от Postman
Нет бесплатной командной работы.
Как системному аналитику мне регулярно нужно проверять работу разных API до того, как ставить задачи на разработку. В банке не оказалось общих коллекций Postman, поэтому пришлось собирать всё с нуля: просить коллег, писать в личку техлидам, пробовать самому.
Когда коллекция была готова, я передал её в команду. Но у каждого появилась своя копия — кто-то дописал, кто-то изменил. В итоге при обмене всё превратилось в кашу: мне скидывают разные версии одной и той же коллекции, и я уже не понимаю, где актуальная.
Автоматизация только за деньги.
Позже я захотел автоматизировать цепочку запросов, чтобы не запускать их вручную. Собрал коллекцию, настроил… но Postman разрешил запускать её ограниченное количество раз. На этом автоматизация и закончилась.
Из-за этих проблем я начал искать альтернативы.
А что есть кроме Postman?
Оказалось, что список альтернатив довольно большой и они довольно интересные. Почти пара десятков вариантов...
...описание которых я спрячу под спойлер.
API Client | Краткое описание | Сайт |
Insomnia | Мощная кросс-платформенная среда для тестирования REST, GraphQL, gRPC и WebSocket | |
SoapUI | Лидер рынка для автоматизированного тестирования SOAP и REST API | |
Katalon Studio | Бесплатная платформа для автоматизации тестирования API с поддержкой SOAP/REST | |
Hoppscotch | Открытая веб-платформа для быстрого тестирования API с поддержкой реального времени | |
Firecamp | Мультипротокольная платформа с поддержкой REST, GraphQL, WebSocket и Socket.IO | |
Bruno | Локальный клиент с акцентом на безопасность и офлайн-работу | |
Restfox | Оффлайн-веб клиент для HTTP-запросов с открытым исходным кодом | github.com/restfox |
gRPC UI | Специализированный инструмент для работы с gRPC API через веб-интерфейс | github.com/grpcui |
Prestige | Текстовый HTTP-клиент с минималистичным интерфейсом для любителей CLI | |
Pororoca | Альтернатива Postman с поддержкой HTTP/ и HTTP/ | github.com/pororoca |
Thunder Client | Легковесное расширение VSCode для быстрого тестирования API | |
Restlet Client | Расширение Chrome для тестирования REST API с импортом коллекций Postman | |
API Tester | Мобильное решение для тестирования API на iOS и Android устройствах | |
RecipeUI | Типобезопасный клиент с автодополнением на базе TypeScript | |
Milkman | Расширяемая платформа для работы с различными типами API-запросов | github.com/milkman |
Nightingale | Нативный REST-клиент для Windows с упором на производительность | github.com/nightingale |
Yaak | Быстрый, работающий в офлайн-режиме и Git-friendly API Client для HTTP, GraphQL, WebSockets, SSE и gRPC |
Но после детального изучения оказалось, что часть платная, как и Postman, часть проприетарная или её нужно разворачивать в виде веб-приложения. И так получилось, что кроме Bruno подходящих вариантов не было.
Bruno — это новый клиент API с открытым исходным кодом (лицензия MIT). Не требует регистрации, в отличии от Postman, работает автономно. Приложение только настольное на Windows, macOS и Linux. Но больше вам, думаю, будет интереснее его функциональность.
По функциональности Postman и Bruno очень похожи. Оба:
поддерживают протоколы HTTP/HTTPS, GraphQL (в Bruno WebSockets не поддерживается);
методы запросов: GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD;
есть утилита для работы из командной строки (CLI);
скриптинг и автоматизация (pre и post requests);
тестирование API;
работа с переменными окружения;
поддержка различных схем авторизации: Basic Auth, OAuth, Bearer token и т.д.
И, последнее, организация запросов: коллекции, папки, рабочие пространства. Эта функциональность мне пригождается постоянно. К примеру, из-за повсеместного использования Postman в банке обычно нет централизованной коллекции, которая бы обновлялась. Поэтому, если нужно тестово вызвать какую-то новую API, то нужно поспрашивать в чате аналитиков, поискать коллекции в поиске Confluence, попробовать собрать запрос самостоятельно из документации. Если это удалось, то запрос останется только у меня, и другой аналитик или тестировщик, столкнувшийся с такой же проблемой, что и я, будет проходить тот же путь.
Невольно думаешь, как было бы здорово иметь общую коллекцию с примерами запросов, которая бы со временем обновлялась. И Bruno может с этим помочь. Я создал коллекции для разных целей, вроде API нашего подразделения, запросы к шине, коллекции с инструментами, вроде создания тестового пользователя.
Поделился с командой через Bitbucket и сейчас у нас есть основная точка синхронизации. Если кому-то что-то нужно вызвать, он может это сделать без тестировщика и другого участника команды.
Подобную коллекцию можно использовать как основу и расширять с помощью создания pull request’ов в main ветку. Если у другой команды или отдела есть желание сделать свою коллекцию, то они могут использовать эту как пример.
Чем Bruno хорош
В этом разделе я вас буду убеждать переходить на Bruno расскажу о специфичной функциональности Bruno и как ей пользоваться, чтобы вам поскорее уйти от Postman 🙃Всё остальное вы сможете найти в документации Bruno.
№1. Локальное хранение коллекции
Коллекции и запросы — это файлы в папке на вашем диске, поэтому вам доступны любые операции, как и с обычными файлами, вроде текстового поиска и замены, настройки CI/CD, возможности резервного копирования, хранения credentials без риска попадания их неизвестно куда и другие.
Коллекции сохраняются в файловой системе (формат Bru) вместо облака, что гарантирует полный контроль над конфиденциальной информацией. Базово, коллекция — это папка со следующими файлами и папками:
bruno.json
{
"version": "1",
"name": "Change card product",
"type": "collection",
"ignore": [
"node_modules",
".git"
]
}
collection.json
auth {
mode: basic
}
auth:basic {
username: admin
password: secret-pass
}
vars:pre-request {
basic-auth: Basic itsbase64encodedstring
}
Дополнительно в папке могут быть переменные окружения коллекции и их значения — могут храниться в папке environments
, и npm пакеты — они хранятся в папке node_modules
.
Пара особенностей:
При раскрытии большой коллекции, больше 50 запросов, нужно будет подождать; но недавно это дело оптимизировали, так что даже большие коллекции Bruno прожуёт.
Нельзя перетаскивать запрос из одной коллекции в другую, так как физически это разные папки. Решение: я копирую cURL запроса в Bruno, который нужно перенести и в другой коллекции создаю запрос с помощью cURL.
№2. Совместная работа
Так как коллекции в Bruno — это файлы, то можно использовать привычные системы контроля версий, вроде Git, для совместной работы. Бесплатно, в отличие от платных workspace в Postman.
Приведу пример, как это может быть полезно при взаимодействии нескольких отделов. Перед установкой на прод новой API она должна быть защищена от IDOR-уязвимостей. Для этого системный аналитик пишет сценарии проверки таких уязвимостей и создаёт коллекцию запросов в Postman для департамента кибербезопасности (ДКБ), чтобы они могли проверить, что API и его отдельные методы безопасны.
По итогу у нас есть общий ресурс в виде Postman коллекции, которую мы кладём в общую папку. Когда приходит время проверять ДКБ достаёт коллекцию из папки, импортирует в Postman и «протыкивает» запросы, проверяя, как они отрабатывают.
Проблемы этого подхода:
Отсутствие контроля версий, что важно для понимания, а не было ли удалено чего лишнего и прочее.
Сложность совместной работы, требующая одному экспортировать коллекцию из Postman и класть в общую папку, а другому скачивать и импортировать коллекцию. Есть риск перепутать старую версию с новой.
Проблемы с автоматизацией. В Postman нельзя бесконечно запускать коллекции, поэтому проверка всё равно будет происходить за счёт «протыкивания» запросов по очереди.
Безопасность. Если доступ к папке есть у кого-то кроме тех, кого касается этот процесс, то они могут забрать пароли и ключи себе, что не очень здорово.
Как ни странно, Bruno решает эти проблемы:
Отсутствие контроля версий и проблемы совместной работы решаются использованием общего репозитория с необходимостью делать pull request’ы в основную ветку. Так туда не попадёт ничего лишнего, и ничего не пропадёт.
Проблема с автоматизацией тоже решится. В Bruno легко настроить создание пререквизитов для запуска коллекции и в процессе выполнения проверок безопасности добавить assert’ы для запуска тестов по каждому запросу. Так сотрудникам отдела ДКБ останется просто запустить коллекцию и проверить, что по всем запросам стоят зеленые галочки. Какие-то непонятные части можно описать в документации.
Проблема с безопасностью решается с помощью файла .env, куда складываются все credentials. Для запуска коллекции нужно будет заполнить пример из хранилища паролей и они подтянутся в коллекцию.
Как поделиться коллекцией через git и удалённый репозиторий
Инициировать репозиторий в папке с коллекциями: git init
Добавить все файлы в папке в отслеживание git:git add .
Добавить удалённый репозиторий. Заменить <remote_repository_url>
на ваш:git remote add origin <remote_repository_url>
Запушить ваши коллекции в репозиторий:git push -u origin HEAD:master
Готово ✨
Как отправить изменения коллекции в удалённый репозиторий
Я покажу на примере IntelliJIdea, так как с помощью неё стягиваю изменения из Bitbucket и отправляю в него. Но можно это делать через VSCode, через terminal или другие инструменты работы с Git.
Алгоритм обновления, возможно, не самый оптимальный, но пока проблем с ним не было.
Открываем папку репозитория в Idea и инструмент с Git.

Коммитим изменения.
Подтягиваем изменения (git pull
) из удалённого репозитория. Если есть конфликты, резолвим их.
Пушим изменения.

Профит.
Теперь вашим коллегам останется склонировать репозиторий или подтянуть изменения себе с помощью git pull. И, возможно, придётся решить конфликты, если их локальные изменения будут отличаться от ваших 😅.
№3. Управление секретами (credentials)
Одной из причин перехода на Bruno может быть возможность безопасно хранить секреты. Разберёмся как это делать.
Прячем значения переменных
Есть 2 типа переменных, которые можно пометить как секреты:
глобальные переменные окружения (Global Environments Variables);
переменные окружения коллекции (Environment Variables).
Глобальные переменные окружения бесполезно помечать как секреты, они не хранятся в файлах коллекции, и нет риска их куда-то нечаянно отправить.
Другое дело — переменные окружения коллекции. Если пометить переменную как секрет, то при экспорте и в файле окружения ./environments/<env-name>
она будет с пустым значением.

Таким образом, это самый простой способ предотвратить распространение секретов.
Но с ним есть одна проблема — как передать коллекцию коллеге, с которым вы вместе работаете над проектом? Переменные ведь никуда не сохраняются. Решение — в следующем разделе.
Создаём .env файл с секретами
Создаём .env файл в корне папки коллекции. Пример создания в терминале:

Задаём наш секрет в формате <key> = <value>
.
Добавляем интерполяцию переменной в Bruno в формате {{process.env.<key>}}
.

Кейс использования. Можно интерполировать process-переменную в значение переменной окружения коллекции и в коллекции использовать переменную окружения. В этом случае галочку в переменной окружения ставить не нужно, иначе её значение не будет сохранено при экспорте. Интерполяция попадёт в файл, и для работы коллекции достаточно будет создать файл с секретом.
Добавляем интерполяцию в переменную окружения коллекции:

Указываем ключ переменной окружения коллекции в запрос:

Готово.
🫢 Вариант с указанием переменной как секрет, подойдет для единоличников, которые боятся отправить креды коллеге при экспорте коллекции.
🔒 Вариант с созданием .env файла подойдет всем остальным, кого волнует безопасность.
Примечание. Про интерполяцию переменных в Bruno можно почитать в официальной документации
№4. Декларативный scripting
Это поддержка упрощенных ассертов через выражения вместо обязательного написания JS-скриптов как в Postman.
Уверен, у каждого тестировщика и аналитика бывает работа, которая требует последовательно вызывать несколько запросов и перекладывать параметры из одного в другой. У меня так было, когда я тестировал дачу согласия на доступ к персональным данным в Госуслугах. Каждый раз после дачи согласия нужно было отзывать его в банке, последовательно вызывав 3 запроса. Похожее происходит при создании нового пользователя для тестирования определённого продукта, вроде заказа кредитной карты.
Решение — сделать последовательность запросов, которые ускорят рутинные операции, и логику между запросами реализовать с помощью Pre- и Post-Script. Собственно, инструкция в гифке ниже.

Удобное создание переменных
В Postman переменные создаются с помощью Post script в таком виде pm.environment.set('my_variable', pm.response.json()[0].some_param);
.
Проблема в том, что для создания нужно каждый раз вспоминать синтаксис Postman и это усложняет настройку цепочки вызовов.
В Bruno есть инструмент для более быстрого создания переменных:
Переходим в запрос и на вкладку «Vars».
В Post Response добавляем переменную с названием.
В значении пишем
JSONPath
до нужного поля в ответе.Profit 🎉.
Теперь переменную можно использовать в следующем запросе.
А чтобы вы знали, какая переменная вам нужна, оставляю шпаргалку с переменными в виде таблицы. Таблица большая, поэтому под спойлером.

Тип переменных | Для чего нужны? | Где настраивается? | Интерполяция переменной | Как управлять в JS | Где хранится? |
Глобальные переменные Global Environment Variables | Если вам нужны переменные доступные во всех коллекциях Если вам нужно делиться этими переменными, то не выйдет. Для этого лучше используйте переменные окружения. | Иконка глобуса 🌐 в правом верхнем углу | Добавить в строку название переменной в фигурных скобках. Пример: {{var_name}} |
| В локальном хранилище приложения |
Переменные окружения Environment Variables | Если вам нужны разные переменные внутри коллекции в зависимости от окружения. Например, если у вас есть тест и препрод. | Нажать на выпадающий список "No Environment" в правом верхнем углу; Нажать "Create Environment" или "Import Environment"; | {{var_name}} |
| В папке ./envoronments в папке коллекции в файле <environment-name>.bru |
Переменные коллекции Collection Variables | Если вам нужны переменные внутри коллекции независимо от окружения, чтобы доступ к ним был из любого запроса в коллекции | Нажать три точки на коллекции; Нажать "Settings"; Выбрать вкладку "Vars"; Добавить нужные переменные для Pre-Request или Post-Response; | {{var_name}} |
| В файле collection.bru |
Переменные папки Folder Variables | Если вам нужны переменные только внутри папки | Нажать три точки на папке; Нажать "Settings"; Выбрать вкладку "Vars"; Добавить нужные переменные для Pre-Request или Post-Response; | {{var_name}} |
| В файле folder.bru в папке с запросами <collection_folder> → <nested_folder> → folder.bru |
Переменные запроса | Если вам нужны переменные только внутри запроса | Открыть запрос; Перейти на вкладку "Vars"; Добавить нужные переменные для Pre-Request или Post-Response; | {{var_name}} |
| В файле запроса |
Runtime переменные | Возникают во время выполнения запроса и доступ к ним есть только во время выполнения запроса. Можно задать в Pre-Request с помощью bru.setVar и интерполировать их в значение заголовка или значение body параметра | {{var_name}} |
| В оперативной памяти | |
Process Environment Variables | Для хранения секретов Создаётся .env файл, который добавляют в gitignore, чтобы пароли и ключи не попали в удалённый репозиторий. Пример такого файла: .env Развернуть исходный код | {{process.env.key}} process.env.<secret-name-from-env-file> |
| В файле .env в папке с коллекцией <collection_folder> → .env |
Хочу отметить, что значения всех переменных в Bruno хранятся как строки, поэтому, если вам нужно сохранить объект, придётся воспользоваться post-scripting и преобразовать объект в строку с помощью JSON.stringify(str)
.
Сохраняем в переменную todoId
значение свойства id шестого объекта из ответа.

Достаём значение переменной todoId
в path
переменную.

Быстрые asserts
В Postman тесты пишутся в Post-response блоке Script. Для написания также нужно помнить синтаксис Postman и написать что-то вроде такого:
pm.test("Status code is 200", () => {
pm.response.to.have.status(200);
});
В Bruno так тоже можно, но есть вариант проще:
Переходим в запрос и на вкладку «Assert».
Нажимаем «Add assertion».
В Expr указываем что хотим проверить. Можно обращаться к Response Object.
В Operator вариант сравнения/проверки.
В Value указываем ожидаемое значение. JFYI: для некоторых проверок оно не нужно.


№5. Фильтрация ответа
Иногда нужно в огромном ответе найти одно значение. Ты ждёшь, когда значение одного параметра изменится на другое и ты сможешь продолжить вызывать другие запросы. Каждый раз вызываешь, скроллишь вниз и ищешь нужный параметр.
Решение есть и в Postman, и в Bruno. В окне ответа пишем JSONPath к нужному параметру.


№6. Дебаг скриптов в Bruno
В Bruno есть возможность писать Pre и Post скрипты. Но как дебажить? В Postman для этого есть консоль. А что в Bruno?
А в Bruno, браузерный DevTools 🙂

№7. Документация
Вещь, которой можно пренебречь при личном использовании коллекций, но которая может сильно помочь при совместном использовании.
В Bruno есть возможность писать документацию на уровне коллекции, папки и запроса. Документации много не бывает 😉

№8. Bruno CLI
Bruno CLI — инструмент командной строки для тестирования API. Он позволяет автоматизировать запуск тестов без сложных настроек. Не пользовался, но знаю, что есть. Ниже кратко о том, что он может.
С его помощью тестировщики могут выполнять отдельные API-запросы или целые коллекции через простые команды, например:
bru run
для всей коллекции илиbru run request.bru
для конкретного запроса.Тесты можно запускать в разных окружениях с помощью параметра
--env
, передавать переменные через--env-var
и использовать CSV-файлы для тестовых данных.CLI генерирует отчёты о результатах тестирования в форматах JSON, JUnit и HTML для последующего анализа. Функционал включает передачу переменных окружения и секретов через опцию
--env-var
. Поддерживается тестирование на основе данных (data-driven testing) с использованием CSV или JSON файлов для множественных тестовых сценариев.
При большом желании можно сделать CI с прогоном тестов из коллекции Bruno.
№9. Data Driven Testing
С помощью этой функции можно итерироваться по запросам на основании данных из CSV или JSON-файлов. Данные из файлов будут подставляться в переменные запросов, и таким образом можно проверить все кейсы одного запроса без необходимости создавать множество запросов и в каждом прописывать разные данные.
Можно использовать через CLI. Через UI эта функция платная.
№ 10. Прототипирование продукта
Об этой функциональности у меня есть история. Однажды мы с командой делали продукт, подразумевающий оркестрацию бизнес-процесса на стороне нашей системы. Это значит, что за получение предложения, получение данных для отображения лендинга продукта, формирование документов, подписание и логирование операций в АБС отвечал наш микросервис. Архитекторы, молчать!
Так вышло, что я забежал дальше разработки и налаживал процесс подписания документов нашей системой и системой подписания. Так как разработка была занята другими задачами, а тестировать подписание нужно было, я собрал весь процесс продукта в виде последовательных запросов в Bruno.
Автоматизация реально облегчила мне жизнь: теперь вместо долгих ручных проверок всё делается почти само, и я больше не трачу кучу времени на поиск мелких ошибок или неправильных параметров в запросах. Особенно круто оказалось, что можно быстро настроить проверки (Assert’ы), чтобы сразу видеть, где что сломалось, а где всё сработало как надо. По сути, теперь для проверки всего пользовательского сценария мне хватает нажать две кнопки — и сразу получаю понятный результат. Если что-то не так, то вижу это мгновенно.
Этот кейс можно реализовать и в Postman, но после 50 запусков коллекции вас попросят заплатить. В Bruno запуск коллекций бесплатный.
А ещё есть
Открытый исходный код (MIT License). Полная прозрачность кодовой базы и возможность самостоятельной модификации против проприетарной модели Postman.
Оффлайн-работа без регистрации. Не требует создания аккаунта и сохраняет функциональность при отсутствии интернета, тогда как Postman зависит от облачной синхронизации.
Безопасность запросов. Выполняет API-вызовы напрямую с локальной машины, исключая риски прокси-серверов Postman, через которые проходят данные.
Гибкая ценовая политика. Все ключевые функции доступны бесплатно (некоторые функции, например, data-driven запросы, в платном тарифе), в отличие от ограничений Postman Free Tier и необходимости платить $14+/пользователь за расширенные возможности.
Нативная работа с NPM-модулями. Прямое подключение библиотек через package.json против сложных обходных решений в Postman.
Неограниченные прогоны коллекций. Отсутствие лимитов на количество запусков тестов в отличие от квот Postman (25-250/месяц в зависимости от тарифа).
Возможность миграции. Поддержка импорта коллекций Postman/Insomnia/OpenAPI v3 с сохранением переменных окружения и тестовых сценариев. Стоит учесть, работает не идеально и нужно проверять.
И в заключение отмечу...
...что Bruno — достойная альтернатива Postman, особенно для корпоративного использования благодаря безопасному хранению коллекций.
Инструмент активно развивается сообществом, регулярно получает обновления и исправления, что положительно сказывается на его стабильности и функциональности. В нашей команде Bruno успешно прошёл проверку на реальных задачах и значительно упростил совместную работу над API. Тестировщик нашей команды практически полностью перешёл на этот инструмент. Хочется верить, что проект привлечёт больше спонсоров и сможет сохранить независимость, продолжая радовать нас новыми возможностями и все департаменты последуют за мной в переходе на Bruno.

Подписывайтесь на Телеграм-канал Alfa Digital — там мы постим новости, опросы, видео с митапов, краткие выжимки из статей, иногда шутим.