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

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

    OpenAPI/Swagger: специфікація як джерело істини

    Зміст

    Уяви: тобі дали новий сервіс і сказали «протестуй API». Перше питання — де взяти правду про те, як цей API має працювати? Сторінка у вікі бреше, бо її писали пів року тому. Розробник відповідає «подивись у код». Postman-колекція колеги покриває третину ендпоінтів. Саме цю проблему розв'язує OpenAPI — формальний машиночитний опис API, який лежить у репозиторії поруч із кодом і слугує єдиним джерелом істини (source of truth) для документації, тестів, моків і клієнтського коду.

    Ця глава недарма стоїть перед тест-дизайном для API: специфікація — це матеріал, з якого тест-дизайн робить кейси. Вміння читати її заощаджує години перепитувань: тест-кейси стають системними («покрив усе, що в контракті»), а не «що згадав — те й перевірив».

    Що таке OpenAPI і до чого тут Swagger

    OpenAPI Specification (OAS) — це стандарт опису HTTP API у форматі YAML або JSON. Один файл (часто openapi.yaml) перелічує всі ендпоінти, їхні параметри, формати запитів і відповідей, коди статусів і правила авторизації. Про сам REST і формати даних ми говорили в розділі про веб — специфікація просто записує все це у строгій, придатній для програмної обробки формі.

    З назвами історична плутанина, яку люблять питати на співбесідах. Спочатку формат називався Swagger; 2015 року SmartBear передала специфікацію під крило OpenAPI Initiative (Linux Foundation), і з версії 3.0 стандарт зветься OpenAPI. Слово «Swagger» лишилося за екосистемою інструментів SmartBear: Swagger UI, Swagger Editor, Swagger Codegen. Тобто коректно так: OpenAPI — специфікація (стандарт), Swagger — інструменти навколо неї. У побуті «подивись у Swagger» майже завжди означає «відкрий Swagger UI з нашою специфікацією».

    Навіщо опис саме машиночитний? Текст у вікі вміє читати тільки людина. А з формального YAML-файлу інструменти автоматично породжують цілу низку артефактів — і всі вони гарантовано узгоджені між собою, бо мають спільне джерело:

    openapi.yaml
    специфікація в репозиторії

    Swagger UI
    інтерактивна документація

    Mock-сервер
    відповіді за схемами

    Кодогенерація
    клієнти, типи, серверні заглушки

    Валідація відповідей
    у тестах

    Контракт
    між командами

    openapi.yaml
    специфікація в репозиторії

    Swagger UI
    інтерактивна документація

    Mock-сервер
    відповіді за схемами

    Кодогенерація
    клієнти, типи, серверні заглушки

    Валідація відповідей
    у тестах

    Контракт
    між командами

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

    Актуальна гілка стандарту — 3.x: найпоширеніші на практиці OpenAPI 3.0 (2017) і 3.1 (2021), у 2025-му вийшла версія 3.2. Стара версія Swagger 2.0 формально називається OpenAPI 2.0 і досі трапляється на легасі-проєктах.

    Структура специфікації: paths, parameters, schemas, responses, $ref

    Ось мінімальна, але цілком робоча специфікація одного ресурсу:

    openapi: 3.0.3
    info:
      title: Users API
      version: 1.0.0
    paths:
      /users/{id}:
        get:
          summary: Отримати користувача за id
          parameters:
            - name: id
              in: path
              required: true
              schema:
                type: integer
          responses:
            '200':
              description: Користувача знайдено
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/User'
            '404':
              description: Користувача з таким id не існує
    components:
      schemas:
        User:
          type: object
          required: [id, email]
          properties:
            id:
              type: integer
            email:
              type: string
              format: email
            name:
              type: string
              maxLength: 50

    Розберімо блоки, з якими працює QA:

    paths — серце специфікації: перелік усіх шляхів і HTTP-методів на кожному. Пара «шлях × метод» називається операцією (operation). Якщо операції немає в paths — з погляду контракту її не існує.

    parameters — усе, що приходить поза тілом запиту: параметри шляху (in: path, як {id} вище), query-параметри (in: query — фільтри, пагінація), заголовки (in: header). У кожного — тип, ознака required, іноді обмеження: enum з допустимими значеннями, minimum/maximum, pattern.

    responses — задокументовані коди статусів і схема тіла для кожного. Це готовий перелік очікуваних результатів: якщо у специфікації для операції описані 200 і 404, обидва сценарії мають бути відтворювані (самі статус-коди — у розділі про веб).

    components/schemas — словник моделей даних. Схема описує форму обʼєкта: які поля, яких типів, які обовʼязкові (required), які обмеження (format, maxLength, enum). Синтаксис схем — це діалект JSON Schema; в OpenAPI 3.1 сумісність із JSON Schema повна, у 3.0 є дрібні відмінності (наприклад, «поле може бути null» у 3.0 позначається окремим ключовим словом nullable: true). Детально про перевірки за JSON Schema — у главі про перевірки відповіді.

    $ref — посилання на вже описаний фрагмент замість копіювання. Рядок $ref: '#/components/schemas/User' каже: «тут та сама схема User». Один опис моделі перевикористовується в десятках операцій, і зміна в одному місці міняє контракт скрізь. Для QA це підказка: якщо схему User поправили, зачеплені всі ендпоінти, які на неї посилаються, — ось і скоуп регресії.

    Swagger UI: специфікація очима людини

    Swagger UI — вебсторінка, яка рендерить специфікацію в інтерактивну документацію: список операцій, розгорнуті схеми, приклади запитів. На багатьох проєктах вона доступна прямо на тестовому стенді за адресою на кшталт /swagger або /api-docs.

    Найкорисніша кнопка — Try it out: заповнюєш параметри, тиснеш Execute — і Swagger UI надсилає справжній запит на середовище й показує справжню відповідь. Це найшвидший спосіб помацати незнайомий API без Postman і curl. Два застереження. Перше: запити справжні — DELETE через Try it out на спільному стенді видалить дані так само, як будь-який інший клієнт. Друге: те, що показує UI (схеми, приклади), — це вміст специфікації, а не поведінка сервера; правдивість цих обіцянок ще треба перевірити.

    Swagger UI зручний для розвідки й разових перевірок; системну роботу з запитами краще вести в Postman або в коді.

    Від специфікації до тест-кейсів

    Головна практична навичка цієї глави: специфікація — це готовий каркас тест-аналізу. Кожен блок відповідає на своє тестове питання:

    БлокЩо там записаноЯкі тести з цього народжуються
    pathsусі операції APIмапа покриття: кожна пара «шлях × метод» викликана хоча б раз
    parametersтипи, required, enum, межіпозитив із валідними значеннями; негатив: пропущений обовʼязковий, чужий тип, значення поза enum
    requestBody + schemasобовʼязкові поля, формати, довжинимежові значення, відсутні required-поля, невалідні формати
    responsesзадокументовані статусиокремий сценарій на кожен статус: як добитися 200, 404, 422
    securitySchemesсхеми авторизаціїзапит без токена і з невалідним токеном (докладно — у главі про авторизацію в API)

    Подивись ще раз на схему User вище — вона сама диктує перевірки. email має format: email — отже, потрібен негативний тест із рядком без «собачки». name має maxLength: 50 — класична пара межових значень: 50 символів проходить, 51 — ні. id та email у required — а name ні, отже, відповідь без name валідна, і клієнт зобовʼязаний таке переживати. Кожне обмеження у схемі — це межа, а межі — улюблене місце проживання багів. Як системно застосовувати техніки еквівалентності й межових значень до параметрів — у главі про тест-дизайн для API; самі техніки — в розділі про тест-дизайн.

    Бонус такого підходу — вимірність. «Я протестував API» — твердження ні про що; «покрито всі операції з paths, для кожної — всі задокументовані статуси плюс негативи за обмеженнями схем» — уже осмислена заявка на покриття, яку можна показати команді.

    Коли дока бреше: розбіжності специфікації й реальності

    Специфікація — джерело істини за задумом, але не за фактом: вона теж написана людьми і теж відстає від коду. Типові розбіжності, які варто шукати свідомо:

    • у реальній відповіді є поля, яких немає у схемі (або навпаки — обіцяне поле не приходить);
    • сервер повертає статус, не описаний у responses: у доці 400, у житті 500;
    • тип не збігається: у схемі id: integer, а приходить рядок "42";
    • поле в required, а насправді буває null чи зникає;
    • параметр позначений required: true, але запит без нього чомусь проходить.

    Кожна така знахідка — дефект. Питання лише, чий: коду чи специфікації. Відповідь залежить від того, як команда працює з контрактом. У підході design-first специфікацію пишуть до коду, вона і є узгодженим контрактом — тоді розбіжність майже завжди баг реалізації. У підході code-first специфікація генерується з анотацій у коді — тоді вона автоматично встигає за кодом, але сумлінно документує і його помилки, а «істина» розмивається. Тестувальнику не треба вирішувати цю суперечку самотужки — треба зафіксувати розбіжність, показати обидві сторони (що обіцяно і що прийшло) і винести на команду. Мовчки підлаштувати тест під фактичну поведінку — найгірший варіант: контракт продовжить брехати наступному, хто його прочитає.

    Розбіжність, яку зловили не тести, а інша команда у своєму продакшн-коді, називається дрейфом схеми (schema drift) — і це вже територія контрактного тестування.

    Валідація відповідей проти схеми

    Очима дрейф не ловиться: поле, що зникло з відповіді, у JSON на пів екрана просто не помітиш. Тому звірку відповідей зі схемами автоматизують — кожен автотест, окрім своїх функціональних перевірок, проганяє тіло відповіді через валідатор схем. У JavaScript/TypeScript стандартний інструмент — Ajv, валідатор JSON Schema:

    import { test, expect } from '@playwright/test';
    import Ajv from 'ajv';
    
    // Схема — з components/schemas специфікації
    const userSchema = {
      type: 'object',
      required: ['id', 'email'],
      properties: {
        id: { type: 'integer' },
        email: { type: 'string' },
        name: { type: 'string', maxLength: 50 },
      },
      additionalProperties: false,
    };
    
    test('GET /users/1 відповідає схемі User', async ({ request }) => {
      const response = await request.get('/api/users/1');
      expect(response.status()).toBe(200);
    
      const ajv = new Ajv();
      const valid = ajv.validate(userSchema, await response.json());
      expect(valid, JSON.stringify(ajv.errors)).toBe(true);
    });

    Зверни увагу на additionalProperties: false — без нього зайві, не описані у схемі поля пройшли б валідацію мовчки, бо за замовчуванням JSON Schema додаткові поля дозволяє. Саме так непомічені поля з персональними даними випливають у публічних відповідях.

    І тверезе застереження: схема перевіряє форму, а не зміст. Відповідь, де email — синтаксично валідна адреса іншого користувача, схему пройде бездоганно. Валідація проти схеми — це страхувальна сітка від дрейфу контракту, а не заміна функціональних перевірок. Як вбудувати її в структуру автотестів — у главі про API-автотести в коді.

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

    • Виглядає як «Swagger — це наша документація», а насправді Swagger UI — лише рендер файлу специфікації. Джерело — YAML/JSON у репозиторії; якщо на стенд задеплоєна стара версія, красива сторінка впевнено бреше.
    • Виглядає як «у специфікації описаний 200 — значить, ендпоінт працює», а насправді специфікація описує намір, а не факт. Це список обіцянок для перевірки, а не результат перевірки.
    • Виглядає як «поле не в required, тестувати нічого», а насправді опціональність — це окрема гілка поведінки: відповідь без цього поля валідна, і все, що її споживає, мусить це переживати. Опціональні поля — класичне гніздо null-багів.
    • Виглядає як «схема пройшла — відповідь правильна», а насправді схема перевіряє типи і структуру, а не бізнес-логіку. Чужі дані правильної форми валідатор пропустить.
    • Виглядає як «додаткових полів у відповіді не буде, у схемі ж їх немає», а насправді без явного additionalProperties: false зайві поля дозволені й валідацію проходять.
    • Виглядає як «дока застаріла, орієнтуюсь на фактичну поведінку», а насправді так контракт остаточно втрачає сенс. Розбіжність — це дефект, який треба зафіксувати, а не обійти.

    Підсумок

    • Специфікація OpenAPI — машиночитний контракт API і єдине джерело істини; Swagger UI — лише її людиночитний рендер.
    • Кожен блок специфікації — готовий чек-лист: paths дає мапу покриття, parameters і schemas — межі й негативи, responses — перелік статусів, кожен з яких треба вміти відтворити.
    • Розбіжність специфікації й реальності — завжди дефект; чий саме (коду чи доки) — вирішує команда залежно від підходу design-first чи code-first, але фіксувати її — робота QA.
    • Валідація відповіді проти схеми ловить дрейф контракту, який не видно очима, — але перевіряє форму, а не зміст.
    • $ref звʼязує схеми в граф: зміна однієї моделі зачіпає всі операції, що на неї посилаються, — це готовий скоуп регресії.

    Що питають на співбесіді

    • «Чим OpenAPI відрізняється від Swagger?» — перевіряють охайність термінології: OpenAPI — стандарт специфікації, Swagger — екосистема інструментів навколо нього (UI, Editor, Codegen). Плутанина пробачна, але точна відповідь одразу додає балів.
    • «Як ти використовуєш специфікацію при тестуванні API?» — чекають системності, а не «дивлюсь у Swagger, що там є»: покриття з paths, негативи з обмежень параметрів і схем, сценарій на кожен задокументований статус.
    • «Реальна відповідь не збігається з докою. Твої дії?» — дивляться на процесне мислення: зафіксувати обидві сторони розбіжності, зʼясувати, що в команді є джерелом істини, завести дефект — а не мовчки підігнати тест під факт.
    • «Як перевірити, що відповідь відповідає схемі?» — хочуть почути про автоматичну валідацію (JSON Schema, Ajv чи аналог) і про її межу: форма — так, бізнес-логіка — ні.
    • «Навіщо машиночитна специфікація, якщо є сторінка у вікі?» — перевіряють розуміння ідеї: з формального опису генеруються узгоджені між собою дока, моки, типи й валідація; вікі ж дрейфує мовчки і нічого не породжує.

    Джерела

    • OpenAPI Specification — актуальний текст стандарту.
    • Learn OpenAPI — офіційний навчальний ресурс OpenAPI Initiative: структура специфікації з прикладами.
    • Swagger UI — офіційна сторінка й документація інструмента.
    • JSON Schema — стандарт опису схем даних, на якому побудовані схеми OpenAPI.
    • Ajv — документація валідатора JSON Schema для JavaScript/TypeScript.