← Design Patterns для автоматизаторів

Конспект і таймкоди

0:00

Одна поведінка для різних платформ

Один business scenario може мати різні UI-кроки на mobile/desktop Web або iOS/Android: відрізняються header, navigation, scrolling, calendar і time picker. Тест при цьому має залишатися спільним за наміром, а platform-specific дії — вибиратися окремо.

Strategy пропонується як спосіб сховати ці відмінності за одним interface. Водночас для першого невеликого набору тестів звичайний if або switch може бути достатнім KISS-рішенням.

6:36

Реалізація Strategy і межа її складності

У прикладі пошук системного setting потребує scroll на iOS і іншої взаємодії на Android. SettingsScreen вибирає IosSettings або AndroidSettings за driver/platform і делегує однаковий публічний метод потрібній реалізації.

Коли різниться багато screens і їх послідовність, кількість strategies швидко зростає. Для двох повністю native codebases автор інколи віддає перевагу окремим Swift/Kotlin test projects з однаковими test cases: вони ближчі до application code і їх легше запускати розробникам.

15:18

Вибір automation layer через архітектуру

React Native app іноді можна переважно тестувати Playwright через web-rendered version, залишивши WebdriverIO/Appium лише для native navigation та системних дій. Це скорочує runtime, якщо основний UI справді доступний як Web.

Перед вибором інструмента потрібно з'ясувати, де реалізована логіка: frontend, mobile client, backend чи database. Network requests через browser tools або proxy показують фактичний consumer/producer contract краще за припущення з UI.

20:00

Monolith, modular monolith і microservices

Monolith тримає систему в одному deployable project, modular monolith розділяє її всередині на чіткі modules, а microservices відокремлюють users, products, auth, statistics та інші capabilities у самостійні services. Структура automation-коду має відображати корисні межі системи, але не копіювати кожен production layer автоматично.

У microservice architecture перед services часто стоять gateway і load balancer. Вони впливають на routing, authentication і failure responses, тому API-тест має розуміти, який саме layer повернув 404 або 5xx.

27:30

Message queues, adapters і перевірка authorization

Kafka, RabbitMQ або Amazon SQS можуть передавати events чи тимчасовий state між services. Один service також може мати різні adapters для REST, gRPC, WebSocket, GraphQL, database або message broker, тому тестова структура групується за реальним resource/transport contract.

На gateway інколи помилково перевіряють лише наявність Authorization і prefix Bearer. Для кожного endpoint корисна негативна перевірка з відсутнім або випадковим token: вона одночасно виявляє слабку authorization, неправильний route і проблеми service registration.

37:30

Від прямого HTTP request до читабельного API

Перший API-test може напряму сформувати URL, headers, credentials, body та перевірити status code. Але десятки низькорівневих рядків приховують намір на кшталт “authorize user” або “create suite”.

Окрім документації HTTP client library, автор радить дивитися її unit/integration tests: там є реальні приклади form parameters, headers, POST body та response handling. Після Proof of Concept повторюваний protocol code ховається за доменними методами.

45:00

MVC/Controller і transport boundaries

Controller у test project об'єднує операції одного resource: create, get, update та інші HTTP calls. Service/package boundary відповідає окремому product service або microservice, наприклад Reporter чи Test Management.

Для REST основою є resources та endpoints; для GraphQL — queries/mutations і domain entities; для WebSocket/gRPC — свої transport adapters. Мета структури — дати тесту короткий domain API, не змішуючи transport details між різними services.

55:00

DTO для request і response

Request і response радять представляти типізованими objects, а не збирати JSON-рядки вручну. DTO групує поля suite, user чи report і дозволяє controller приймати один аргумент замість довгої сигнатури.

На ранньому етапі можна тимчасово витягнути одне поле через JSONPath, якщо повна model ще не потрібна. Коли перевірки розширюються до всього response, цей seam замінюється DTO без зміни business flow тесту.

1:00:00

Auth state і controller context

Token можна зберігати у змінній test class, fixture/context або окремому state object; вибір залежить від lifecycle test runner і потрібної ізоляції. API authorization допустимо перевіряти багато разів, на відміну від дорогого UI-login у кожному тесті.

Controller може зберігати token як context і автоматично додавати header до calls. Порожній token дає змогу тим самим controller перевірити unauthorized flow. Controllers одного domain можна об'єднати facade-подібним entry point, якщо це справді скорочує тест.

1:10:00

API versioning і OpenAPI models

v1, v2 і наступні versions дозволяють підтримувати mobile clients та third-party integrations, які залежать від старого response shape. Tests для обох контрактів краще розділити явно, а не наповнювати один controller умовами.

OpenAPI/Swagger schema може згенерувати request/response models і clients для Java, C#, Python або TypeScript. Це економить ручне створення DTO, але generated code потрібно перевірити: його default exception handling не завжди зручний для negative API assertions.

1:20:00

Modules, Controllers, Services і DAO

Великий test project можна розділити на modules за services прямо на root-рівні, а всередині тримати Controllers, Services і data access. Це відповідає modular monolith підходу й зменшує змішування різних domain areas.

Controller визначає доступні operations, Service збирає business sequence, а DAO ізолює роботу з database. DAO/ORM автор радить додавати лише тоді, коли тести реально працюють з багатьма tables; для кількох запитів окремий layer може бути зайвим.

1:35:00

ORM entities і перетворення data layers

Hibernate або Entity Framework можуть mapити database rows у UserEntity, SuiteEntity та інші types. Models можна повторно використати через спільну library або підтримувати окремо в test project, якщо прямої залежності від application code немає.

Backend flow часто проходить repository/DAO → entity → DTO → controller response. Розуміння цих перетворень допомагає локалізувати mismatch між database state й API JSON, але automation-код не повинен відтворювати всю production реалізацію.

1:45:00

Response Decorator і custom assertions

Response wrapper/decorator може централізовано перевіряти status code, витягувати body та формувати зрозуміле failure message. Коли однакові checks дублюються між controllers, вони переносяться у resource-specific assertion class, наприклад assertions для suite response.

Generated API clients часто кидають exceptions на 4xx/5xx, через що negative tests змушені розбирати exception body і status. Окрема assertion layer може бути простішою. AssertJ-style generated assertions і обов'язкові пояснення because покращують grouping однакових failures у report.

1:55:00

Мінімальний набір повторюваних патернів

Автор підсумовує практичний набір: Page Object, Adapter/Delegate, Chain of Responsibility, Decorator, Facade, Value Object, Factory Method, Strategy, State, Controller і DTO. Це не каталог заради каталогу, а повторювані seams для UI, API, data generation і assertions.

XUnit patterns також дають назви для assertion methods, assertion messages і test-data factories. Їх потрібно вводити після появи дублювання або нечіткого contract, а не будувати всі наперед.

2:00:00

TypeScript API-приклад і role-specific UI

У TypeScript-прикладі factory method створює registration DTO з random data, Controller приймає DTO, Axios config зберігає базові settings, а response decorator порівнює фактичний JSON з типізованою model. Якщо поле відсутнє, custom error підказує class і type, які потрібно оновити.

Для продукту з різними clients, roles і permissions UI-перевірки краще групувати невеликими components або role-specific classes. Менші класи полегшують code review і зменшують merge conflicts, але надмірне дроблення так само небажане; shared page behavior залишається спільним.

2:20:00

Enums і завершальний принцип

Для environment і platform радять використовувати typed enums замість порівняння випадкових strings: dev, stage, prod, iOS, Android, Web. Це дає autocomplete і чітко обмежує допустимі значення.

Завершальна думка: Controller, DTO та інші патерни мають залишатися гнучкими й простими. Структура тестів починається з фактичної architecture та поточного contract, а ускладнюється лише коли з'являється відповідна проблема.