vyvchy
    Теми розділу

    04 · API-тестування

    API-тестування: об'єкт перевірки, рівні й інструменти

    Зміст

    Половина того, що робить застосунок, ніколи не показується на екрані. Кнопка «Оформити замовлення» — це лише обгортка над запитом, який летить на сервер, змінює баланс, списує товар зі складу, надсилає лист і повертає відповідь. UI показує вам щасливий кінець («Дякуємо за замовлення!»), але не показує, що в тілі відповіді ціна прийшла від'ємна, що замовлення створилося двічі або що чужий користувач може прочитати ваш чек, підмінивши один номер у запиті. Усе це живе на рівні API — і саме тому API-тестування перевіряє логіку там, де вона насправді працює.

    Ця глава — карта розділу. Ми розберемо, що таке API-тестування і чим воно відрізняється від тестування через інтерфейс, де воно стоїть у піраміді тестів, що саме на цьому рівні перевіряють, які бувають типи API і чим їх ганяти — від однорядкового curl до автотестів у коді. Далі кожна тема отримає власну главу; тут — фундамент, на який вони спираються.

    Що означає «тестувати API»

    API (application programming interface) — це контракт, за яким одна програма звертається до іншої. У вебі це майже завжди HTTP-запит на певний URL з певним методом і тілом, у відповідь на який сервер повертає , заголовки й тіло (зазвичай JSON). Якщо клієнт-серверна модель і формати даних для вас ще туман — почніть із глав «Клієнт-сервер і як працює веб» та «REST API та формати даних»; тут ми на них спираємось.

    Тестувати API означає слати запити безпосередньо до цього інтерфейсу й перевіряти відповідь — не відкриваючи браузер і не клікаючи кнопок. Замість «заповнити форму й натиснути Save» ви надсилаєте POST /api/orders з готовим JSON-тілом і перевіряєте, що прийшов статус 201, у тілі є id створеного замовлення, а сам запис справді з'явився. Ви працюєте з системою мовою, якою розмовляють її власні компоненти.

    запит напряму

    UI-тест: увесь шлях

    Браузер

    Фронтенд

    API / бекенд

    База даних

    API-тест

    запит напряму

    UI-тест: увесь шлях

    Браузер

    Фронтенд

    API / бекенд

    База даних

    API-тест

    Ключова ідея вже на цій діаграмі: UI-тест проходить увесь стек — браузер, верстку, JavaScript, мережу, бекенд, базу. API-тест заходить збоку, одразу в бекенд, оминаючи весь фронтенд. Тому він швидший, стабільніший і бачить те, чого не видно з екрана.

    Чим API-тести відрізняються від тестування через UI

    «Чому» тут важливіше за «як». UI-тест відповідає на питання «чи може користувач зробити X через інтерфейс?» — і платить за це повнотою стека: він повільний, бо чекає рендеринг і анімації, і крихкий, бо ламається від зміни верстки, яка ніяк не стосується логіки. API-тест відповідає на інше питання — «чи правильно поводиться бізнес-логіка й дані?» — і за рахунок вужчого зрізу отримує швидкість і стабільність.

    АспектЧерез UIЧерез API
    Що перевіряєУвесь стек очима користувачаЛогіку й дані бекенду
    ШвидкістьСекунди на тестДесятки–сотні мілісекунд
    СтабільністьЛамається від зміни версткиЛамається від зміни контракту, а не верстки
    Що видноТільки те, що показує UIСтатус, усі поля тіла, заголовки
    Підготовка данихДовга, через кроки в UIШвидка, одним запитом

    З таблиці не варто робити висновок «API краще за UI». Вони відповідають на різні питання. Кнопка може бути прив'язана до неправильного , поле — не відправлятися, помилка з API — не показуватися користувачу: усе це ловить лише UI-тест. Тому це не заміна, а розподіл праці — і його формалізує піраміда.

    Місце в піраміді тестування

    — орієнтир, що показує, скільки тестів варто мати на кожному рівні. Знизу — багато дешевих і швидких модульних (unit) тестів; посередині — інтеграційні та API-тести; згори — мало повільних наскрізних (E2E) тестів через UI.

    E2E / UI — мало, повільні, крихкі

    API / інтеграційні — золота середина

    Unit — багато, швидкі, дешеві

    E2E / UI — мало, повільні, крихкі

    API / інтеграційні — золота середина

    Unit — багато, швидкі, дешеві

    API-рівень — та сама золота середина. Він на порядок швидший і стабільніший за E2E, але, на відміну від unit-тестів, ганяє систему зібраною: справжній сервер, справжня база, справжня серіалізація. Одним API-тестом ви покриваєте цілий бізнес-сценарій, який через UI тягнув би десяток крихких кроків. Тому типова порада — переносити перевірки якнайнижче: усе, що можна перевірити на рівні API, не варто перевіряти через браузер. Детальний розбір рівнів, вартості й антипатернів (як-от «пісочний годинник» чи «ріжок морозива») — у розділі «Автоматизація»; тут достатньо запам'ятати, що API-тести — робоча конячка більшості команд.

    Що саме перевіряємо на рівні API

    Об'єкт перевірки на рівні API — п'ять речей. Кожній далі присвячена окрема глава, тут — короткий орієнтир.

    Типи API оглядово

    «API» — не один протокол. На співбесіді корисно розрізняти хоча б п'ять і розуміти, чим тестування кожного відрізняється.

    ТипТранспорт і форматЩо характерно для тестування
    RESTHTTP + JSONРесурси й методи (GET/POST/PUT/DELETE), статус-коди несуть сенс
    SOAPXML поверх HTTPСуворий контракт (WSDL), громіздкі конверти, живе в enterprise/легасі
    GraphQLHTTP + JSON, один ендпоінтКлієнт сам описує запит; у легасі-режимі статус не є оракулом, помилки — в масиві errors
    gRPCRPC, за замовчуванням protobufБінарний формат, у браузері не подивишся як JSON, потрібен grpcurl/код
    ВебхукиВихідний HTTP-запитЦе сервер стукає до вас; треба приймач, а не запит

    REST — найпоширеніший стиль: система як набір ресурсів, доступних за URL, з методами HTTP і осмисленими статус-кодами. Йому присвячена більшість цього розділу. SOAP старіший і формальніший — обмін XML-конвертами за строгим описом WSDL; ви зустрінете його переважно в банках і телекомі. GraphQL перевертає підхід: один ендпоінт, а клієнт запитом описує, які саме поля хоче; це породжує власні пастки, розібрані в «GraphQL: особливості тестування». gRPC — бінарний і швидкий, для зв'язку між сервісами; його разом із SOAP і чергами розбирає «SOAP, gRPC і асинхронні API».

    Окремо стоять вебхуки (webhooks): тут напрям зворотний — не ви шлете запит, а зовнішня система сама надсилає HTTP-запит на ваш URL, коли стається подія (оплата пройшла, лист доставлено). Щоб їх перевірити, потрібен не клієнт, а ; стратегія — у «Мокання залежностей: стаби, mock-сервери, вебхуки». Реалтайм-канали на кшталт WebSocket — ще один окремий світ, описаний у веб-главі «WebSockets і реалтайм».

    Інструментарій: від curl до коду

    Інструменти вишиковуються в природну сходинку — від найшвидшого разового пострілу до повноцінної автоматизації.

    curl HTTP-клієнт, який є майже на кожній машині. Ідеальний, щоб швидко перевірити один запит або вкласти точну команду відтворення в баг-репорт:

    curl -i -X POST https://api.example.com/orders \
      -H "Authorization: Bearer TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"productId": 42, "qty": 2}'

    -i покаже статус і заголовки відповіді — те, що на рівні API часто важливіше за тіло.

    Postman — найпопулярніший графічний клієнт: колекції запитів, змінні оточення, вбудовані скрипти-перевірки, спільна робота команди. З нього зручно починати ручне дослідження API; йому присвячені «Postman: основи» і глава про скрипти й Newman. Insomnia — легший клієнт із тією ж ідеєю. Bruno — молодший конкурент, який зберігає колекції звичайними файлами прямо в репозиторії, тож їх видно в git поряд із кодом; це зручно для рев'ю й версіонування.

    Верхня сходинка — код. Коли перевірок стають десятки, вони мають ганятися в CI на кожен і сплітатися в ланцюжки (створити → прочитати → видалити), графічний клієнт стає тісним. Тоді запити пишуть у тестовому фреймворку. У Playwright для цього є вбудований APIRequestContext:

    test('створення замовлення повертає 201 і id', async ({ request }) => {
      const response = await request.post('/api/orders', {
        data: { productId: 42, qty: 2 },
      });
      expect(response.status()).toBe(201);
      const body = await response.json();
      expect(body.id).toBeTruthy();
    });

    Той самий запит, що й у curl, але вже з перевіркою, повторюваний і придатний для CI. Як будувати такі тести, клієнти й ланцюжки — у «API-автотести в коді: клієнти, структура, ланцюжки». А підглянути реальні запити застосунку, перш ніж відтворювати їх у тесті, найзручніше через вкладку Network у DevTools.

    Ручне vs автоматизація

    Ручне API-тестування (через Postman чи curl) незамінне, коли ви вивчаєте незнайомий API, робите дослідницьку перевірку гіпотези, відтворюєте баг або ганяєте одноразовий сценарій. Тут швидкість зворотного зв'язку важливіша за повторюваність.

    Автоматизація виправдана там, де перевірки треба повторювати часто й однаково: , ланцюжки CRUD, запуск на кожен коміт у CI, перевірка десятків комбінацій параметрів. API-рівень — узагалі найвдячніший кандидат на автоматизацію: тести швидкі, стабільні й не залежать від верстки. На практиці ці два режими не конкурують — руками досліджують і формулюють перевірку, а те, що варто стерегти постійно, переносять у код. Чому API-тести все одно бувають нестабільними й що з цим робити — у «Стабільність API-тестів: флак, асинхронність, дебаг».

    Баги, які видно лише на рівні API

    Це головний аргумент, чому QA спускається під UI. Ціла категорія дефектів на екрані невидима — інтерфейс їх приховує або просто не показує.

    • 200 OK, а всередині помилка. Сервер повернув «успіх», але в тілі — {"error": "insufficient funds"} або порожній список замість даних. UI може відрендерити це як порожній екран, і тест «зелений». На рівні API ви бачите розбіжність статусу й тіла одразу.
    • Зайві поля у відповіді. Ендпоінт користувача повертає ще й passwordHash чи isAdmin — фронтенд їх просто не показує, тож витік даних лишається непоміченим, поки хтось не гляне в сире тіло.
    • Валідація лише на фронтенді. Форма не пускає від'ємну кількість, але сам ендпоінт приймає qty: -5 без питань. Реальний зловмисник шле запит повз браузер — саме так треба тестувати й вам.
    • Доступ до чужих даних перебором id. GET /api/orders/123 віддає чуже замовлення, бо сервер не перевіряє власника (клас /BOLA). З UI такого посилання просто немає, а запит працює.
    • Гонки й неідемпотентність. Два однакові POST створюють два замовлення; повторний платіж проходить двічі. Крізь UI такий сценарій відтворити важко, а прямими запитами — тривіально.
    • Неправильні статус-коди. На неіснуючий ресурс приходить 200 замість 404. Для користувача різниці немає, для клієнта API — критична. А от 404 замість 403 на чужий ресурс дефектом сам по собі не є: власник має право не підтверджувати існування ресурсу тим, у кого немає прав, — багом це стає лише за розбіжності із задокументованим контрактом конкретного API.

    Саме ця категорія робить API-тестування обов'язковою навичкою, а не приємним доповненням.

    Типові помилки

    • Виглядає як «тест зелений, статус 200 — усе працює», а насправді статус каже лише, що запит дійшов і сервер не впав; помилка може сидіти в тілі відповіді. Статус і тіло перевіряють окремо.
    • Виглядає як «UI не пускає невалідні дані, отже, бекенд захищений», а насправді валідація часто лише на фронтенді, і прямий запит проходить те, що форма блокує. Негативні перевірки треба слати повз UI.
    • Виглядає як «API-тести швидкі й стабільні, замінімо ними всі UI-тести», а насправді API не бачить зламану верстку, неправильну прив'язку кнопки чи те, що помилка не показується користувачу. Рівні доповнюють, а не заміняють один одного.
    • Виглядає як «поле не показується в застосунку, значить, його немає», а насправді відповідь може містити зайві чутливі поля, які фронтенд просто не рендерить. Дивіться сире тіло, а не екран.
    • Виглядає як «GraphQL повернув 200, запит успішний», а насправді в легасі-режимі application/json статус не є : реальні помилки лежать у масиві errors, тож дивитися треба в тіло.

    Підсумок

    • API-тестування — це запити безпосередньо до інтерфейсу між компонентами, в обхід UI; воно швидше, стабільніше й бачить те, чого не видно з екрана.
    • API-тести й UI-тести відповідають на різні питання й доповнюють один одного; API-рівень — «золота середина» піраміди й головний кандидат на автоматизацію.
    • Об'єкт перевірки — п'ять зрізів: функціональність, дані, контракт, помилки, доступи.
    • Типів API кілька (REST, SOAP, GraphQL, gRPC, вебхуки), і тестуються вони по-різному; статус-код сам по собі ніколи не є доказом успіху.
    • Інструмент вибирають під задачу: curl/Postman — для дослідження й відтворення, код — для регресії в CI.

    Можливі питання

    • «Чим API-тестування відрізняється від UI-тестування?» Інтерв'юер перевіряє, чи розумієте ви, що це різні зрізи, а не заміна: API — швидкість, стабільність і доступ до сирих даних/статусів; UI — увесь стек очима користувача. Слабка відповідь зводиться до «API без браузера»; сильна називає, що саме кожен рівень ловить, а другий пропускає.
    • «Де API-тести в піраміді й чому саме там?» Хочуть почути про баланс вартості й стабільності: API-рівень покриває бізнес-логіку дешевше й надійніше за E2E, тому перевірки переносять якнайнижче.
    • «Що ви перевіряєте у відповіді на запит?» Тут відсіюють тих, хто дивиться лише на статус. Сильний кандидат перелічує статус-код, тіло (значення й типи полів), заголовки, схему й побічний ефект (чи справді змінився стан).
    • «Наведіть баг, який видно лише на рівні API.» Годяться 200 з помилкою в тілі, валідація лише на фронтенді, зайві поля у відповіді, доступ до чужих даних перебором id. Конкретний приклад цінується вище за визначення.
    • «Чим ви тестуєте API?» Перевіряють кругозір і доречність: curl/Postman для ручного дослідження, код у фреймворку для регресії в CI — і розуміння, коли переходити від одного до іншого.

    Джерела

    Що означає «тестувати API»

    • Learn OpenAPI — Introduction (OpenAPI Initiative) — API визначає дозволені взаємодії між двома програмами; сторони — постачальник і , а сам API вважається непорушним контрактом.
    • MDN — An overview of HTTP — HTTP як клієнт-серверний протокол: рівно два типи повідомлень — запит і відповідь, і ініціює їх отримувач ресурсу.
    • ISTQB CTFL Syllabus v4.0.1 — перевірка інтерфейсів і взаємодій між компонентами — це інтеграційне тестування; окремого рівня «API testing» силабус не виділяє.

    Чим API-тести відрізняються від тестування через UI

    • Mike Cohn — The Forgotten Layer of the Test Automation Pyramid — три названі властивості тестів через інтерфейс — крихкі, дорогі, повільні — плюс четверта, забута: часткова надлишковість.
    • MDN — An overview of HTTP — протокол не має стану: два послідовні запити нічим не повʼязані — звідси самодостатність окремого запиту в тесті.
    • Roy T. Fielding — дисертація, гл. 5 (REST) — обмеження stateless: кожен запит містить усе потрібне для його розуміння, тож стан для сценарію готується одним запитом.

    Місце в піраміді тестування

    • Mike Cohn — The Forgotten Layer of the Test Automation Pyramid — першоджерело піраміди: рівнів три, модульні в основі, інтерфейс нагорі («we want to do as little of it as possible»), середній шар — забутий.
    • The Practical Test Pyramid (Ham Vocke, martinfowler.com) — пізніший коментар: із піраміди варто винести два правила — тести різної гранулярності й тим менше тестів, чим вищий рівень.
    • Martin Fowler — TestPyramid (bliki) — піраміда як збалансований портфель: низькорівневих тестів має бути значно більше за наскрізні.
    • Software Engineering at Google — гл. 11: Testing Overview — деформації піраміди з назвами й причинами: «ріжок морозива» і «пісочний годинник».
    • ISTQB CTFL Syllabus v4.0.1 — канон пірамідою не оперує: рівні розрізняються за обʼєктом, цілями, й відповідальністю.

    Що саме перевіряємо на рівні API

    • RFC 9457 — Problem Details for HTTP APIs — розділення шарів: статус-код несе загальну семантику для HTTP-софту, а тіло — специфіку API, на яку реагує клієнт.
    • JSON Schema Validation, draft 2020-12 — зріз «дані»: схема стереже форму — required перевіряє лише наявність імені властивості, format типово є анотацією.
    • OWASP API1:2023 — Broken Object Level Authorization — зріз «доступи»: перевірка прав на рівні обʼєкта має стояти на кожному ендпоінті, що приймає ідентифікатор.
    • OWASP API Security Top 10 — 2023 — перелік 2023: BOLA — номер один, BFLA — доступ до чужих ресурсів і адміністративних функцій.

    Типи API оглядово

    Інструментарій: від curl до коду

    • ISTQB CTFL Syllabus v4.0.1 — силабус говорить категоріями інструментів (проєктування й реалізація тестів, виконання й вимірювання ), а не брендами.
    • OpenAPI Specification — специфікація сама називає інструменти тестування серед споживачів машиночитного опису API.
    • Playwright — API testingAPIRequestContext у Playwright: тестувати API, готувати серверний стан і перевіряти серверні пост-умови.

    Ручне vs автоматизація

    • ISTQB CTFL Syllabus v4.0: тести одночасно проєктують, виконують і оцінюють, вивчаючи тестовий обʼєкт; корисне за браку специфікацій і за дефіциту часу.
    • ISTQB CTFL Syllabus v4.0.1 — чому саме регресія: регресійні ганяють багато разів, і кількість кейсів росте з кожною ітерацією.
    • ISTQB CTAL-TAE Syllabus v2.0 — що дає автоматизація: те, чого руками зробити неможливо, — паралельність, віддалене виконання, консистентність між циклами.

    Баги, які видно лише на рівні API

    • RFC 9457 — Problem Details for HTTP APIs — статус повідомляє загальну семантику, а причину й деталі кладуть у тіло — звідси розбіжність «200 і помилка всередині».
    • OWASP API1:2023 — Broken Object Level Authorization — доступ до чужого обʼєкта: ідентифікатор легко знайти в шляху, query, заголовках чи тілі, і тип ідентифікатора значення не має.
    • OWASP API Security Top 10 — 2023API3:2023 обʼєднує зайві дані у відповіді й mass assignment: спільна причина — брак перевірки прав на рівні властивості обʼєкта.
    • IETF Internet-Draft — The Idempotency-Key HTTP Header Field (-06) — дедуплікація повторів: генерує клієнт, а ресурс за ним впізнає той самий запит.
    • MDN — 403 Forbidden404 замість 403 легітимне: власник має право не підтверджувати існування ресурсу тим, у кого немає прав.

    Типові помилки

    Пояснення

    «Поясни» працює з власним API-ключем Anthropic: запит іде з вашого браузера прямо до Anthropic.

    Свій API-ключ (BYOK)

    Вставте власний ключ Anthropic — пояснення працюватиме на реальній моделі. Ключ зберігається лише у вашому браузері (localStorage), нікуди не надсилається, крім api.anthropic.com, і не логується.