2. API автоматизація одразу правильно, MVC, pydantic
Практична побудова API-тестів навколо Testomat.io: генерація `Pydantic`-моделей з `OpenAPI`, розділення запитів за resource controllers, спільний `BaseController`, авторизація через fixtures та валідація response schema. Головна мета — не просто перевіряти окремі поля `dict`, а отримувати типізований об’єкт і одразу виявляти розбіжності між очікуваним контрактом і реальною API-відповіддю.
Примітка: конспект укладено за автоматичними українськими субтитрами; назви API, Python-бібліотек і методів нормалізовано за контекстом відео.
Після цього уроку ви зможете
Згенерувати чернетку Pydantic-моделей з OpenAPI і відредагувати її під фактичний response.
Розділити API-код на BaseController, resource controllers, models і pytest fixtures.
Валідувати response через model_validate(), а aliases і nullable types описувати явно.
Здіагностувати schema mismatch, circular import і fixture discovery за traceback і pytest output.
Замість того щоб працювати з response як із набором рядків і dictionary keys, пропонується описати його через Pydantic. Так тест перевіряє не лише наявність значення, а й структуру, типи та обов’язковість полів.
Джерелом схеми може бути OpenAPI-специфікація Testomat.io. Якщо документації немає, модель можна початково згенерувати з реального JSON через JSON-to-Pydantic і потім відредагувати. Автор одразу попереджає: навіть офіційна специфікація може відставати від фактичної response schema.
Що змінилося після запису
Pydantic validation не завжди є strict
АктуальноCurrent Pydantic v2 documentation states that input may be converted to declared types and extra fields are ignored by default. Якщо API-тест має виявляти будь-який schema drift, strict behavior і extra='forbid' треба задати явно.
Що змінилосяНе встановлено: точну Pydantic version у відео не названо.
Перевірено 2026-07-31
Термін
Pydantic model_validate()
Class method, який перевіряє вхідний object проти model schema і повертає model instance або піднімає ValidationError.
До проєкту додаються pydantic і datamodel-code-generator. Генератор приймає локальну схему або URL, обирає Pydantic BaseModel як output і зберігає Python-моделі у src/api/models.
Довгу CLI-команду краще винести в project configuration: там фіксуються input, output, версія Python і правила aliases. Згенерований файл — це стартова точка, а не готова доменна модель: автоматичні назви і надто загальні класи ще доведеться уточнювати.
Що змінилося після запису
Генератору потрібно явно вказати Pydantic v2 output
АктуальноCurrent datamodel-code-generator docs recommend --output-model-type pydantic_v2.BaseModel for new Pydantic v2 projects; backward-compatible default pydantic.BaseModel targets v1. Для code з model_validate() output type треба фіксувати явно.
Що змінилосяНе встановлено: версію generator у відео не названо.
Перевірено 2026-07-31
Термін
datamodel-code-generator
Library і CLI utility, що генерує Pydantic-моделі з OpenAPI 3, JSON Schema та інших структурованих sources.
Показано спрощене застосування Model–View–Controller. Model описує DTO і response data; Controller інкапсулює запити; роль view у цьому тестовому контексті не розвивається.
Кожен REST resource — projects, suites, runs, templates, tests, users — отримує власний controller з потрібними операціями create, get, update, delete. Це тримає тестовий сценарій на рівні предметних дій, а URL, headers і розбір response залишаються в одному місці.
BaseController приймає base URL і JWT, формує спільні headers Authorization і Content-Type: application/json, виконує HTTP-запит і піднімає exception для неуспішного статусу. Методи get, post і put повторно використовують цю поведінку; post і put додатково приймають request body.
Запити варто логувати, щоб під час падіння було видно method, endpoint і контекст виклику. Для requests таке logging додають явно; HTTPX має власний logging namespace, тому конкретна реалізація залежить від обраного client.
pytest fixtures виконують login, отримують JWT і передають його до ProjectController чи SuiteController. Якщо token вже збережено у scope fixture, нова авторизація не потрібна.
Для створення suite спершу потрібен target project. Його можна підготувати окремою fixture або отримати в самому тесті через ProjectController.get_all(). Вибір залежить від того, чи це спільний precondition, чи важливий крок конкретного сценарію.
SuiteController.create() приймає project_id, title і description, формує payload та викликає post базового controller. Потрібні поля звіряються не лише з документацією, а й з request у browser DevTools. У демо офіційна схема містить сумнівну вимогу до suite_id до створення suite, тож real request і response виступають важливою перевіркою контракту.
Відповідь Testomat.io загортає основну сутність у поле data. Після response.json() тест бере response_data["data"] і валідує саме цю вкладену структуру.
Практика
Замкнути API-ланцюжок
Створити suite у target project через SuiteController.
Отримати створену сутність через API і провалідувати response Pydantic-моделлю.
Повторити цей flow для test case через TestController.
Результат: Два API-тести проходять без UI-кроків і виявляють schema mismatch.
PydanticModel.model_validate(response_data["data"]) перетворює dictionary на типізований object і водночас перевіряє schema. Модель suite зводиться до реальних полів на кшталт id, type, attributes і relationships, а зайві generated wrappers видаляються.
Якщо JSON-ключ не є коректним Python-ідентифікатором, наприклад містить дефіс, для поля задається alias. У коді зберігається snake_case, а Pydantic зіставляє його з оригінальною назвою в JSON.
Термін
Field alias
Альтернативна назва field для validation чи serialization; дозволяє зіставити JSON-ключ із Python identifier.
Згенерована models.py містить багато загальних класів на кшталт Attributes1, Attributes2, тому його краще використовувати як reference і поступово називати моделі за їхньою предметною роллю.
Під час демо тест падає через неправильні imports і видалену fixture. Для circular import корисно читати останній змістовний фрейм traceback: там зазвичай вказано реальний модуль і напрям залежності. Якщо pytest не знаходить fixture, він друкує перелік усіх доступних fixtures, що допомагає помітити назву або проблему з discovery.
Щоб показати цінність schema validation, тип одного поля навмисно змінюється на str. Pydantic одразу повідомляє шлях до поля, очікуваний тип і фактичне None.
Якщо None справді дозволено контрактом, тип має це відображати, наприклад str | None. Any варто залишати лише для поля, структура якого справді нестабільна або не важлива для поточної перевірки.
Домашнє завдання — створити suite у вибраному project, отримати його через API і перевірити результат. Потім той самий підхід застосовується до test case: потрібно реалізувати TestController, request model, response model і перевірку створеної сутності.
Базові HTTP-методи, headers, error handling і logging перевикористовуються з BaseController. Якщо documentation schema неповна, спершу виконується реальний request, а його JSON response перетворюється на початкову Pydantic-модель. Помилки validation у цьому процесі допомагають поступово відтворити фактичний контракт.