Postman: основи
Зміст
Postman — найпоширеніший інструмент ручного API-тестування і майже гарантована тема співбесіди для trainee/junior: тебе можуть попросити прямо на дзвінку зібрати запит, підставити токен і додати перевірку. Але цінність Postman не в тому, що він «вміє надсилати запити» — це вміє й curl. Цінність у тому, що він перетворює купу разових запитів на організований, документований і повторюваний артефакт: колекцію, яку можна передати колезі, запустити цілком і навіть вбудувати в CI. Хто розуміє цю логіку, той відрізняється від кандидата, який «тикав у Postman» — і саме цю різницю перевіряє інтервʼюер.
Ця глава — базова: структура, змінні, авторизація і перші перевірки. Скрипти, ланцюжки запитів, прогін із CSV та Newman — у наступній главі «Postman: скрипти, data-driven, Newman». Якщо ти вже щодня працюєш з API з коду і Postman тобі не потрібен — цю главу можна пропустити при першому проході й повернутися до неї перед співбесідою: питають про неї часто.
Запит → папка → колекція
Базова одиниця в Postman — запит (request): метод, URL, параметри, заголовки, тіло. Це рівно ті самі складові HTTP-запиту, які розібрані в главі «HTTP: методи, структура, заголовки» — Postman нічого не додає до протоколу, він лише дає зручну форму для його заповнення.
Запити групуються в папки (folders), а папки — у колекцію (collection). Ієрархія проста, але за нею стоїть важлива ідея: колекція — це не «тека з файлами», а самостійний артефакт зі своїми налаштуваннями, документацією, авторизацією і змінними, які успадковуються вниз по дереву. Саме колекцію ти експортуєш у JSON, шариш команді, запускаєш цілком у Collection Runner чи Newman.
Два поширені способи організувати колекцію:
| Підхід | Структура | Коли доречний |
|---|---|---|
| За ресурсами API | Папки Users, Orders, Payments — усередині CRUD-запити | Дослідження API, регресійний набір, документація |
| За сценаріями | Папки «Реєстрація», «Оформлення замовлення» — усередині кроки флоу | Наскрізні бізнес-флоу, де запити залежать один від одного |
Обидва підходи робочі, головне — послідовність. І назви: запит Get user ні про що не каже, коли їх у колекції п'ятдесят. Краще називати за перевіркою або призначенням: «Створення користувача з валідними даними», «GET неіснуючого id → 404». Це той самий принцип, що й з тест-кейсами: назва описує, що перевіряємо, а не куди ходимо.
Документування запитів
У Postman кожен рівень ієрархії — колекція, папка, запит — має поле опису з підтримкою Markdown. Це виглядає як необов'язкова формальність, але насправді це найдешевша жива документація API в команді: опис лежить поруч із робочим запитом, а не в застарілому Confluence.
Що варто фіксувати в описах:
- На рівні колекції — що це за API, яке середовище потрібне, як отримати доступ (де взяти токен, кого просити про акаунт).
- На рівні папки — контекст ресурсу чи сценарію: передумови, порядок виконання, відомі обмеження.
- На рівні запиту — призначення, обов'язкові параметри, неочевидні значення полів, посилання на вимогу чи тікет.
Другий інструмент документування — збережені приклади (examples). До запиту можна прикріпити пару «запит + відповідь»: реальну відповідь сервера зберігаєш як приклад, і тепер будь-хто бачить очікуваний формат тіла, не виконуючи запит і не маючи доступу до середовища. Приклади також живлять mock-сервери Postman — про це в наступній главі.
З колекції Postman вміє згенерувати веб-документацію: описи, приклади і згенеровані фрагменти коду збираються в сторінку, яку можна опублікувати. Для QA це означає просту дисципліну: підтримуєш колекцію охайною — отримуєш документацію безкоштовно. Якщо ж у проєкті є специфікація OpenAPI, вона лишається первинним джерелом істини, а колекція — робочим інструментом поруч із нею (докладно — у главі «OpenAPI/Swagger: специфікація як джерело істини»).
Environment і рівні змінних
Уяви колекцію з п'ятдесятьма запитами, у кожному захардкоджено https://staging.example.com. Завтра треба прогнати те саме на dev — і ти редагуєш п'ятдесят URL руками. Це головний біль, який лікують змінні (variables).
Змінна вставляється в будь-яке місце запиту через подвійні фігурні дужки: URL стає {{baseUrl}}/api/users, заголовок — Bearer {{token}}. Перед надсиланням Postman підставляє значення. А середовище (environment) — це іменований набір змінних під конкретний стенд: environment dev тримає свій baseUrl і token, environment staging — свої. Перемикаєш середовище в розкривному списку — і та сама колекція працює проти іншого стенда без жодної правки запитів.
Змінні живуть на кількох рівнях (scopes), і це улюблене питання співбесід:
- Global — видимі звідусіль, незалежно від колекції та середовища. Зручно для справді спільного (наприклад, версія API), небезпечно для всього іншого: глобальні змінні «протікають» між незв'язаними колекціями.
- Collection — прив'язані до колекції та їдуть разом з нею при експорті. Гарне місце для констант, що описують сам API: базові шляхи, дефолтні значення полів.
- Environment — прив'язані до стенда. Усе, що відрізняється між dev/staging/prod: хости, облікові дані, токени.
- Local — існують лише під час виконання конкретного запиту чи прогону, задаються зі скриптів. Значення, які треба передати з одного запиту в наступний, зазвичай зберігають не в local, а в environment- чи collection-змінну — ланцюжки запитів це тема наступної глави.
Є ще п'ятий скоуп — data: змінні з CSV/JSON-файлу під час data-driven прогону в Collection Runner (за пріоритетом — між environment і local). У щоденній роботі він не трапляється, тож докладно — у наступній главі.
Коли одна й та сама назва визначена на кількох рівнях, перемагає вужчий скоуп:
Тобто local перекриває environment, environment — collection, collection — global. Практичний наслідок: якщо «змінна не змінюється, хоч я її редагую» — майже напевно ти редагуєш її в одному скоупі, а запит бере значення з вужчого.
Ще одна деталь, яку варто знати до того, як вона вкусить: у значення змінної є дві іпостасі — спільне (те, що синхронізується з командним воркспейсом і потрапляє в експорт) і локальне (тільки на твоїй машині). Класично Postman показував їх як два окремі поля — initial value (спільне) і current value (локальне); у нових версіях модель спростили — значення локальне за замовчуванням, а спільним воно стає лише коли ти його явно «шариш». Правило гігієни від зміни назв не залежить: секрети (токени, паролі) тримай лише в локальному значенні, а спільне лишай порожнім або з плейсхолдером. Інакше твій робочий токен поїде всій команді разом із колекцією.
І остання пастка рівня «перший день із Postman»: якщо середовище не вибране або змінної в ньому немає, Postman не падає з помилкою — він надсилає запит із літеральним текстом {{baseUrl}} в URL. Зовні це виглядає як «сервер недоступний» чи дивна помилка резолвінгу імені, а насправді просто не підставилась змінна. В інтерфейсі нерозв'язана змінна підсвічується червоним — варто виробити звичку дивитися на це перед натисканням Send.
Авторизація: auth helpers і спадкування
Більшість реальних API вимагають автентифікації, і додавати заголовок Authorization руками в кожен запит — шлях до розсинхрону. Postman для цього має вкладку Authorization з готовими помічниками (auth helpers): Basic Auth, Bearer Token, API Key, OAuth 2.0 та інші. Помічник — це не окрема магія, а генератор: на основі введених даних він формує правильний заголовок (або query-параметр — для API Key це налаштовується) у момент надсилання. Сам механізм цих схем — Basic, токени, OAuth — розібраний у главі «Автентифікація та авторизація»; тут важлива інструментальна частина.
Ключова можливість — спадкування (inheritance). Вкладка Authorization є не лише в запиту, а й у папки та колекції, і в кожного запиту за замовчуванням стоїть режим «Inherit auth from parent». Це означає: налаштуй авторизацію один раз на рівні колекції — і всі запити її отримають автоматично.
Схема гнучка: колекція задає дефолт, окрема папка може його перекрити (наприклад, папка «Адмінські операції» ходить під іншим токеном), окремий запит — теж (запит «логін без токена» ставить собі No Auth). Разом зі змінними це складається в робочий патерн:
- Токен лежить в environment-змінній
{{token}}(у current value). - Авторизація налаштована один раз на колекції: тип Bearer Token, значення —
{{token}}. - Усі запити успадковують. Токен протух — оновлюєш одну змінну. Перемкнув середовище — під'їхав токен іншого стенда.
Питання «де в Postman зберігати токен і як не дублювати його в 50 запитах» — класика співбесід саме тому, що відповідь вимагає скласти докупи обидві теми: змінні та спадкування. А функціональні перевірки самої авторизації — хто до чого має доступ, 401 проти 403 — окрема велика тема глави «Авторизація в API: ролі, доступи, негативні сценарії».
Прості перевірки зі сніпетів
Досі Postman був «зручним curl»: надіслав запит, очима глянув відповідь. Перший крок від ручної перевірки до автоматичної — тести: JavaScript-код, який виконується після отримання відповіді (вкладка Tests; у нових версіях Postman — Scripts → Post-response). Писати його з нуля не обов'язково: праворуч від редактора є панель сніпетів (snippets) — готових заготовок, які вставляються одним кліком.
Мінімальний набір, з якого всі починають:
// Сніпет "Status code: Code is 200"
pm.test("Статус-код 200", () => {
pm.response.to.have.status(200);
});
// Сніпет "Response body: JSON value check" (адаптований)
pm.test("Створений користувач має числовий id", () => {
const body = pm.response.json();
pm.expect(body.id).to.be.a("number");
pm.expect(body.email).to.eql("qa@example.com");
});
Що тут відбувається: pm.test оголошує іменовану перевірку, pm.response дає доступ до відповіді, а pm.expect — це асерт-бібліотека Chai, вбудована в Postman. Тест вважається пройденим, якщо жоден асерт усередині не впав. Результати з'являються у вкладці Test Results поруч із відповіддю: зелені passed, червоні failed з текстом помилки.
Навіщо це, якщо можна глянути очима? Три причини:
- Повторюваність. Перевірка виконується однаково щоразу — і коли запит запускаєш ти, і коли колега, і коли Collection Runner жене всю колекцію.
- Захист від «200 OK з помилкою в тілі» — класичної пастки, коли статус успішний, а в тілі лежить помилка. Тест на конкретне поле тіла ловить це автоматично; докладно про пастку — у главі «Перевірки відповіді: статус, тіло, заголовки, схема».
- Місток до автоматизації. Колекція з тестами — це вже прогінний набір: у наступній главі ці ж тести поїдуть у Collection Runner з CSV-даними та в Newman у CI.
Важлива чесна межа: тести в Postman — це перевірки відповідей, а не повноцінний тест-фреймворк. Коли з'являються складні ланцюжки, спільні хелпери, code review тестової логіки — команди переходять на код (Playwright APIRequestContext, supertest тощо; огляд інструментів — у главі «API-тестування: об'єкт перевірки, рівні й інструменти»). Postman найсильніший у дослідженні API, ручних перевірках і швидкій регресії без інфраструктури.
Типові помилки
- Виглядає як «сервер лежить», а насправді не вибране середовище. Запит полетів з літеральним
{{baseUrl}}замість хоста — звідси помилка з'єднання. Перша перевірка при дивних мережевих фейлах у Postman — чи підставились змінні (вони підсвічені червоним, якщо ні). - Виглядає як «Postman ігнорує мою змінну», а насправді конфлікт скоупів. Змінна з тією ж назвою визначена і в environment, і в колекції — редагуєш одну, а запит бере іншу, бо вужчий скоуп перемагає. Ліки: одна змінна — один дім, дублікати між скоупами не заводити.
- Виглядає як зручність, а насправді витік секрету. Токен вписано у спільне (initial value) значення змінної або захардкоджено прямо в заголовку запиту — і він їде в командний воркспейс чи git разом з експортом колекції. Секрети живуть тільки в локальному (current value) значенні.
- Виглядає як баг доступів, а насправді розсинхрон копій токена. Авторизація налаштована вручну в кожному запиті; токен оновили — половина запитів повертає 401. Ліки: спадкування від колекції плюс токен у змінній, одна точка оновлення.
- Виглядає як покриття тестами, а насправді порожня обгортка.
pm.testбез жодного асерта всередині завжди зелений — тест, який нічого не перевіряє, гірший за відсутній, бо створює фальшиву впевненість. Коженpm.testмає містити хоча б одинpm.expectабоpm.response.to....
Підсумок
- Колекція — не тека, а артефакт: структура, документація, авторизація і змінні їдуть разом з нею при експорті, шарингу та прогоні.
- Змінні мають рівні global → collection → environment → local, і вужчий скоуп завжди перекриває ширший; environment — стандартне місце для всього, що відрізняється між стендами.
- Секрети — тільки в локальному значенні (current value): спільне значення (initial value) синхронізується з командою і потрапляє в експорт.
- Авторизацію налаштовують один раз на рівні колекції через auth helper і змінну-токен; запити успадковують, окремі папки чи запити можуть перекрити.
- Тести зі сніпетів (
pm.test+pm.expect) перетворюють ручний перегляд відповіді на повторювану перевірку — це перший крок до Collection Runner і Newman.
Що питають на співбесіді
- «Які рівні змінних є в Postman і який пріоритет?» — очікують перелік global/collection/environment/local і правило «вужчий перемагає». Сильна відповідь додає практичний наслідок: чому дублікат змінної у двох скоупах — джерело плутанини.
- «Як прогнати одну колекцію на dev і staging без правки запитів?» — перевіряють розуміння environment: хости й креденшали в змінних середовища, перемикання одним списком.
- «Де зберігати токен авторизації?» — інтерв'юер дивиться, чи складеш ти докупи змінні + спадкування (environment-змінна, auth на рівні колекції) і чи знаєш про initial/current value та гігієну секретів.
- «Як у Postman додати перевірку без написання складного коду?» — очікують сніпети,
pm.test, перевірку статусу і поля тіла; плюс розуміння, що перевіряти статус недостатньо. - «Коли Postman перестає вистачати?» — питання на зрілість: сильний кандидат чесно окреслює межу (складні ланцюжки, review тестового коду, масштабна автоматизація → код) замість «Postman вміє все».
Загальний фільтр інтерв'юера тут — чи розумієш ти систему (артефакт-колекція, скоупи, спадкування), чи просто запам'ятав, куди клікати.
Джерела
- Postman Docs — Store and reuse values using variables — рівні змінних, пріоритет вужчого скоупу, локальні та спільні значення.
- Postman Docs — Add API authorization details to requests — auth helpers і «Inherit auth from parent».
- Postman Docs — Write scripts to test API response data — пост-response скрипти,
pm.*API, сніпети. - Chai BDD API — довідник асертів, які стоять за
pm.expect.
Що таке колекція в Postman і чим вона відрізняється від простої теки із запитами?
Тека лише групує вміст, а колекція (collection) несе власні налаштування: документацію, авторизацію і змінні, що поширюються вниз по дереву на папки й запити. Ієрархія проста: запит (request) з методом, URL, параметрами, заголовками й тілом → папка (folder) → колекція. Ключова ідея в тому, що саме колекція — одиниця експорту в JSON, шарингу команді й запуску цілком у Collection Runner чи Newman, і разом із нею їдуть і змінні рівня колекції, і налаштована авторизація. Тому «зібрати запит у Postman» і «зібрати колекцію» — різні рівні: перше вміє й curl, друге перетворює разові запити на повторюваний артефакт. Саме за цим розумінням — колекція як артефакт, а не тека — інтерв'юер і відсіює тих, хто лише клікав по кнопках.
Як краще організувати колекцію — за ресурсами чи за сценаріями?
Обидва варіанти робочі, вибір залежить від мети. Організація за ресурсами API (папки Users, Orders, Payments з CRUD-запитами всередині) зручна для дослідження API, регресійного набору й документації. Організація за сценаріями (папки «Реєстрація», «Оформлення замовлення» з кроками флоу) підходить для наскрізних бізнес-флоу, де запити залежать один від одного. Головне — послідовність усередині колекції та осмислені назви: імʼя на кшталт Get user втрачає сенс, щойно запитів стає кілька десятків. Краще називати за перевіркою чи призначенням — «Створення користувача з валідними даними», «GET неіснуючого id → 404», — як і з тест-кейсами: з назви має бути видно суть перевірки, а не маршрут, яким ходить запит.
Навіщо документувати запити в Postman, якщо є Confluence чи OpenAPI?
Бо опис у Postman живе там само, де й робочий запит, — тож у нього значно більше шансів лишатися актуальним, ніж у сторінки Confluence, яку востаннє правили пів року тому. Кожен рівень ієрархії (колекція, папка, запит) має поле опису з підтримкою Markdown: на рівні колекції фіксують, що це за API і як отримати доступ; на рівні папки — контекст ресурсу чи сценарію; на рівні запиту — призначення, обов'язкові параметри, посилання на тікет. З охайної колекції Postman ще й генерує веб-документацію майже безкоштовно. Конкурентом OpenAPI це не робить: за наявності специфікації первинне джерело істини — вона, а колекція працює поруч як робочий інструмент, не заміна.
Що таке збережені приклади (examples) і навіщо вони?
Приклад (example) — прикріплена до запиту пара «запит + відповідь»: зберіг реальну відповідь сервера — і формат тіла тепер видно без виконання запиту й без доступу до стенда. Це знімає класичне питання «а що цей ендпоінт узагалі повертає» без витрат на доступи й без ризику зачепити дані. Приклади також живлять mock-сервери Postman — можна віддавати збережену відповідь ще до того, як бекенд готовий. Для QA це дешевий спосіб зафіксувати контракт відповіді просто в колекції.
Що таке змінні в Postman і як вставити змінну в запит?
Змінна (variable) — іменоване значення, яке підставляється в запит перед надсиланням, щоб не хардкодити одне й те саме в десятках місць. Синтаксис — подвійні фігурні дужки в будь-якому місці запиту: {{baseUrl}}/api/users в URL, Bearer {{token}} у заголовку. Проблема, яку це лікує, — колекція з п'ятдесятьма запитами, де скрізь захардкоджено хост: змінити стенд означало б редагувати всі п'ятдесят руками. Зі змінною хост лежить в одному місці, і його підміна автоматично розходиться по всіх запитах.
Як прогнати одну колекцію на dev і staging без правки запитів?
Через середовища (environments). Середовище — це набір значень змінних для одного стенда: у dev свої {{baseUrl}} і {{token}}, у staging — свої. У запитах скрізь стоять змінні, а не літеральні хости, тож вибір іншого середовища зі списку переводить усю колекцію на інший стенд — самі запити правити не треба. Усе, що відрізняється між dev/staging/prod — хости, облікові дані, токени — живе в environment-змінних. Це і є стандартна відповідь на питання про мультистендовий прогін: різницю виносимо у середовище, запити лишаємо незмінними.
Які рівні змінних є в Postman і який у них пріоритет?
Базових рівнів (scopes) чотири: global, collection, environment, local — і вужчий скоуп завжди перекриває ширший (п'ятий, data, з'являється лише в data-driven прогонах Collection Runner). Global доступні з будь-якої колекції та середовища — тому годяться хіба для справді спільних значень, а для решти небезпечні: «протікають» туди, де їх ніхто не чекає. Collection живуть у колекції та їдуть з нею при експорті — місце для констант самого API. Environment описують конкретний стенд — усе, що відрізняється між dev/staging/prod. Local зʼявляються лише на час виконання запиту чи прогону й задаються зі скриптів. Коли одна назва визначена на кількох рівнях, перемагає вужчий: local перекриває environment, environment — collection, collection — global. Практичний наслідок і улюблена пастка співбесід: симптом «редагую змінну, а значення не змінюється» майже завжди означає, що та сама назва живе у двох скоупах — правиш ширший, а запит читає вужчий.
У чому різниця між initial value і current value, і де зберігати токен?
initial value — те, що бачить команда: воно синхронізується з воркспейсом і їде в експорт; current value ніколи не покидає твою машину. Історично це були два окремі поля в редакторі змінних; новіші версії Postman модель спростили: у змінної одне значення, локальне за замовчуванням, і команді воно стає видимим лише після явного шарингу. Гігієна секретів за будь-якої моделі однакова: токени й паролі — тільки в локальному значенні (current value), а спільне (initial value) — порожнє або з плейсхолдером. Порушиш це правило — і робочий токен розʼїдеться командою через синхронізацію, експорт чи git: класичний випадок «виглядає як зручність, а насправді витік секрету».
Запит летить, а сервер начебто недоступний. З чого почати діагностику в Postman?
Перша підозра — не мережа, а нерозв'язана змінна. Коли середовище не вибране або в ньому немає потрібної змінної, Postman не скаржиться — він просто шле рядок {{baseUrl}} як частину URL, і замість відповіді прилітає помилка з'єднання чи резолвінгу імені, яку легко сплутати з падінням сервера. Нерозв'язану змінну інтерфейс підсвічує червоним, тож перша перевірка при дивних мережевих фейлах — чи підставились змінні і чи вибране потрібне середовище. Друга типова причина того ж симптому — конфлікт скоупів: змінна з тією ж назвою визначена і в environment, і в колекції, редагуєш одну, а запит бере іншу. Звичка дивитися на підсвічування перед натисканням Send економить години «полювання за примарою».
Що таке auth helpers і як працює «Inherit auth from parent»?
auth helper — генератор заголовка авторизації: на вкладці Authorization обираєш схему (Basic Auth, Bearer Token, API Key, OAuth 2.0), вводиш дані, а коректний заголовок Authorization (для API Key — за вибором заголовок або query-параметр) Postman збирає сам під час надсилання. Це не окрема магія, а зручна форма для того самого заголовка, який інакше довелося б писати руками. Ключова можливість — спадкування (inheritance): налаштувати Authorization можна на трьох рівнях — запит, папка, колекція, — і запит з коробки стоїть у режимі «Inherit auth from parent», тобто бере auth у батька. Налаштував авторизацію один раз на рівні колекції — усі запити отримали її автоматично, а окрема папка чи запит за потреби перекриють (папка «Адмінські операції» під іншим токеном, запит «логін без токена» — No Auth).
Де зберігати токен авторизації, щоб не дублювати його в 50 запитах?
Скласти докупи дві теми — змінні та спадкування. Токен кладемо в environment-змінну {{token}} (у current value, бо це секрет), авторизацію налаштовуємо один раз на рівні колекції: тип Bearer Token, значення — {{token}}. Усі запити успадковують її через «Inherit auth from parent», тож токен фізично лежить в одному місці. Коли токен протухає, правиться одна змінна замість п'ятдесяти запитів, а зміна середовища автоматично підтягує токен відповідного стенда. Альтернатива «вписати токен вручну в кожен запит» дає класичний баг: оновили токен — половина запитів повертає 401 через розсинхрон копій. Саме тому це питання — класика співбесід: відповідь показує, чи розумієш ти систему зі скоупів і спадкування, чи просто пам'ятаєш, куди клікати.
Як у Postman додати перевірку без написання складного коду?
Через сніпети (snippets) — готові заготовки коду праворуч від редактора тестів, які вставляються одним кліком. Тест — це шматок JavaScript, який Postman виконує щойно прийшла відповідь (історично вкладка Tests, у нових версіях — Scripts → Post-response), і писати його з нуля не обов'язково. Мінімальний набір, з якого всі починають, — сніпет перевірки статус-коду (pm.response.to.have.status(200)) і перевірки поля тіла. Після прогону вкладка Test Results поруч із відповіддю показує, що пройшло (зелений passed), а що впало (червоний failed з текстом помилки). Це перший крок від «глянув очима» до повторюваної перевірки, яка виконується однаково і в тебе, і в колеги, і коли Collection Runner жене всю колекцію.
Що таке pm.test, pm.response і pm.expect, і коли тест вважається пройденим?
Це три опори тестів у Postman. pm.test оголошує іменовану перевірку (перший аргумент — назва, другий — функція з асертами). pm.response дає доступ до відповіді сервера — статус, тіло (pm.response.json()), заголовки. pm.expect приходить із бібліотеки асертів Chai, яку Postman постачає з коробки, — звідси ланцюжковий BDD-синтаксис (pm.expect(body.id).to.be.a("number")). Зеленим тест стає лише тоді, коли всі асерти всередині пройшли. Тому логіка проста: pm.test — обгортка з іменем, а реальну перевірку роблять асерти всередині; без жодного асерта тест завжди зелений і нічого не гарантує.
Чому перевіряти лише статус-код недостатньо?
Через класичну пастку «200 OK з помилкою в тілі»: сервер віддає успішний статус, а в тілі лежить помилка або порожні чи некоректні дані. Тест, який асертить тільки status(200), таке пропустить і створить фальшиву впевненість. Тому мінімальна змістовна перевірка додає асерт на конкретне поле тіла — що id числовий, що email дорівнює очікуваному, — і саме поле тіла ловить розбіжність автоматично. Це та сама дисципліна, що з негативними тестами: успішний статус — необхідна, але не достатня умова коректної відповіді.
Чому pm.test без асерта всередині гірший за відсутній тест?
Бо він завжди зелений і бреше про покриття. pm.test вважається пройденим, якщо жоден асерт усередині не впав — а якщо асертів немає взагалі, падати нічому, і перевірка світиться passed, не перевіривши нічого. Це гірше за відсутній тест, бо створює фальшиву впевненість: у звіті зелено, а фактичного контролю немає. Мінімальна вимога: всередині кожного pm.test — хоча б один справжній асерт (pm.expect чи pm.response.to...). Порожня обгортка — це «виглядає як покриття, а насправді порожня обгортка».
Коли Postman перестає вистачати і команда переходить на код?
Postman перевіряє відповіді, але тест-фреймворк не замінює — межа настає, коли з'являються складні ланцюжки запитів, спільні хелпери й потреба в code review тестової логіки. Тоді команди переходять на код: Playwright APIRequestContext, supertest тощо — там є нормальна структура, версіонування, рев'ю й перевикористання. При цьому сильні сторони Postman нікуди не зникають: дослідження API, ручні перевірки, швидка регресія без розгортання інфраструктури. Сильна відповідь на співбесіді чесно окреслює цю межу замість «Postman вміє все» — це питання на зрілість, а не на знання кнопок.
Три кейси, які складають базу Postman у робочий патерн: налаштувати авторизацію один раз через environment і рівень колекції, діагностувати «сервер недоступний», що насправді є нерозв'язаною змінною, і перетворити ручний перегляд відповіді на повторювану перевірку зі сніпета — а потім перенести ту саму перевірку в код. Скрізь — що робити і чому саме так.
Кейс 1. Авторизація один раз: environment + рівень колекції
Колекція з п'ятдесятьма запитами, кожен ходить під Bearer-токеном. Спокуса — вписати заголовок Authorization у кожен запит; наслідок — токен протух, і половина колекції червоніє 401, бо оновити п'ятдесят копій руками ніхто не встигне. Правильний патерн складає докупи змінні та спадкування: токен лежить в одному місці, авторизація налаштована теж в одному.
Що і де налаштувати:
| Що | Де | Значення |
|---|---|---|
| Хост стенда | environment dev / staging, змінна baseUrl | https://staging.example.com |
| Токен | environment, змінна token, тільки current value | сам токен (секрет) |
| Тип авторизації | вкладка Authorization колекції | Bearer Token, значення {{token}} |
| Запити | режим «Inherit auth from parent» (дефолт) | — |
Далі в самих запитах URL пишеться через змінну, а не через літеральний хост:
GET {{baseUrl}}/api/users/42
POST {{baseUrl}}/api/orders
Що дивитися і чому:
- Токен — у current value, не в initial value. initial value синхронізується з командним воркспейсом і потрапляє в експорт колекції; вписаний туди робочий токен поїде всій команді або в git. current value лишається лише на твоїй машині — це єдине безпечне місце для секрету.
- Auth — на рівні колекції, запити успадковують. Один раз обраний Bearer Token зі значенням
{{token}}на колекції автоматично застосовується до всіх запитів, бо в них стоїть «Inherit auth from parent». Токен протух — оновлюєш одну змінну; перемкнув середовище наdev— під'їхавtokenіbaseUrlіншого стенда. - Виняток перекривається локально. Папка «Адмінські операції» ставить собі власний Bearer з іншою змінною, запит «логін без токена» — No Auth. Спадкування задає дефолт, а не жорстке правило.
Кейс 2. «Сервер недоступний» — таблиця рішень
Симптом упізнаваний: натиснув Send, а замість відповіді — помилка з'єднання або дивний резолвінг імені. У Postman перша підозра тут не мережа, а підстановка змінних: якщо середовище не вибране або змінної в ньому немає, Postman не падає з помилкою, а надсилає запит із літеральним текстом у URL.
# Так виглядає запит, коли змінна не підставилась:
GET {{baseUrl}}/api/users/42
└─ Postman шле це буквально, хоста немає → «сервер недоступний»
Порядок діагностики:
| Симптом | Що перевірити | Ймовірна причина |
|---|---|---|
Помилка з'єднання, у URL видно {{baseUrl}} | Чи вибране середовище в розкривному списку | Середовище не вибране або немає змінної |
| Змінна підсвічена червоним в інтерфейсі | Наведи курсор — Postman покаже «unresolved» | Немає такого імені в активному скоупі |
| Змінна є, але значення «старе», хоч ти його редагував | Де саме визначена ця назва — в environment і в колекції одночасно? | Конфлікт скоупів: вужчий перекриває ширший |
| Запит іде на не той хост | Яке середовище активне | Вибрано prod замість staging |
Що дивитися і чому:
- Нерозв'язана змінна підсвічена червоним. Це найдешевша перевірка: перед Send кинь оком на URL і заголовки — червоне означає, що підстановки не буде. Звичка дивитися сюди економить години «полювання за примарою».
- Конфлікт скоупів дає симптом «Postman ігнорує мою змінну». Одна назва визначена і в environment, і в колекції — редагуєш одну, а запит бере іншу, бо вужчий скоуп (environment) перекриває ширший (collection). Ліки: одна змінна — один дім, дублікати між скоупами не заводити.
Кейс 3. Перша перевірка зі сніпета — і місток у код
Досі Postman був «зручним curl»: надіслав, очима глянув відповідь. Перший крок до автоматичної перевірки — тест зі сніпета: вставляєш заготовку одним кліком і адаптуєш під поле, яке насправді важливе.
// Сніпет "Status code: Code is 200", адаптований під створення (201)
pm.test("Статус-код 201", () => {
pm.response.to.have.status(201);
});
// Сніпет "Response body: JSON value check", адаптований під конкретні поля
pm.test("Створений користувач має числовий id і правильний email", () => {
const body = pm.response.json();
pm.expect(body.id).to.be.a("number");
pm.expect(body.email).to.eql("qa@example.com");
});
Та сама перевірка мовою Playwright APIRequestContext — коли колекція переростає в код:
import { test, expect } from '@playwright/test';
test('POST /users створює користувача з валідними даними', async ({ request }) => {
const res = await request.post('https://staging.example.com/api/users', {
headers: { Authorization: `Bearer ${process.env.TOKEN}` },
data: { email: 'qa@example.com', name: 'QA' },
});
expect(res.status()).toBe(201);
const body = await res.json();
expect(typeof body.id).toBe('number');
expect(body.email).toBe('qa@example.com');
});
Що дивитися і чому:
- Перевірка поля тіла ловить «200 OK з помилкою в тілі». Асерт лише на статус пропустив би успішну відповідь з порожнім чи неправильним тілом. Перевірка
idіemailробить статус необхідною, але не достатньою умовою — розбіжність спливає автоматично. pm.testбез асерта — порожня обгортка. Тест зелений, лише якщо жоденpm.expectусередині не впав; коли асертів немає взагалі, він завжди passed і нічого не гарантує. Коженpm.testмає містити хоча б одинpm.expectабоpm.response.to....- Токен у коді береться з оточення, а не хардкодиться. У Postman секрет живе в current value, у коді — у
process.env.TOKEN. Принцип той самий: секрет не потрапляє в артефакт, який шариться чи їде в git. - Це та сама перевірка, інша інфраструктура. У Postman вона повторювана в Collection Runner і Newman; у коді — версіонована, з рев'ю й спільними хелперами. Межу переходять, коли з'являються складні ланцюжки й потреба ревʼювати тестову логіку.
Колекція, папки, запити
- Розумію, що колекція — не тека з файлами, а артефакт: структура, документація, авторизація і змінні їдуть разом з нею при експорті, шарингу й прогоні; саме колекцію запускають у Collection Runner чи Newman.
- Можу пояснити два підходи до організації (за ресурсами vs за сценаріями) і коли який доречний.
- Розумію, чому запити називають за перевіркою чи призначенням, а не
Get user— той самий принцип, що й з іменуванням тест-кейсів: назва описує, що перевіряємо.
Документування
- Можу пояснити, що поле опису з Markdown є на кожному рівні (колекція / папка / запит) і що фіксувати на кожному.
- Знаю, що таке збережені приклади (examples) і як вони показують формат відповіді без доступу до середовища й живлять mock-сервери.
- Розумію, що з охайної колекції генерується веб-документація, але за наявності OpenAPI саме вона лишається первинним джерелом істини, а колекція — інструментом поруч.
Змінні та середовища
- Можу вставити змінну через
{{baseUrl}}/Bearer {{token}}і пояснити, який біль це лікує (хардкод хоста в 50 запитах). - Розумію, що environment — іменований набір змінних під стенд, і як перемиканням середовища прогнати колекцію на dev/staging без правки запитів.
- Знаю рівні змінних (global, collection, environment, local; у Collection Runner додається data), правило «вужчий скоуп перекриває ширший» і чому дублікат назви у двох скоупах — джерело плутанини («редагую одну, а запит бере іншу»).
- Знаю різницю initial value (спільне, їде в експорт) vs current value (локальне) і що секрети живуть лише в current value.
- Розумію, чому нерозв'язана змінна дає літеральний
{{baseUrl}}в URL, виглядає як «сервер недоступний» і підсвічена червоним.
Авторизація і спадкування
- Можу пояснити, що auth helper — генератор заголовка
Authorization(Basic, Bearer, API Key, OAuth 2.0), а не окрема магія. - Знаю, як працює «Inherit auth from parent», і що авторизацію налаштовують один раз на колекції, а папка чи запит можуть її перекрити.
- Можу скласти робочий патерн: токен у
{{token}}(current value) + Bearer на рівні колекції + спадкування = одна точка оновлення. - Розумію, чому ручне дублювання токена в кожному запиті дає 401 на половині після оновлення (розсинхрон копій).
Перевірки зі сніпетів
- Знаю, що тести — це JS після відповіді (Tests / Scripts → Post-response) і що сніпети вставляють заготовки одним кліком.
- Можу пояснити роль
pm.test(іменована перевірка),pm.response(доступ до відповіді),pm.expect(асерти Chai) і коли тест зелений. - Розумію пастку «200 OK з помилкою в тілі» і чому перевірки лише статусу недостатньо.
- Знаю, чому
pm.testбез асерта завжди зелений і гірший за відсутній тест. - Можу окреслити межу Postman: перевірки відповідей, не фреймворк; складні ланцюжки й рев'ю коду → перехід на код (Playwright APIRequestContext, supertest).
Чим колекція в Postman відрізняється від простої теки із запитами?
Питання
Колекція в Postman — це тека з файлами чи щось більше?