Selenium Page object models
Уточнює Page Object, Page Component Object і допустиму readiness verification.
Неймінг та структура automation-проєкту → Першоджерело ↗Відеобібліотека
Пошук у нотатках курсу Java з переходом на потрібну секунду.
Уточнює Page Object, Page Component Object і допустиму readiness verification.
Неймінг та структура automation-проєкту → Першоджерело ↗Pinned приклад пов’язує API client і Page Object із переходом уроку від прямого UI-flow до reusable automation structure. Код не скопійовано через відсутність LICENSE у repository.
Практика курсу на YOY, домашні завдання та формат ПМП → Першоджерело ↗Object для дискретної частини page, яку можна вкладати в Page Object і повторно використовувати в кількох pages.
Неймінг та структура automation-проєкту →Виняткова перевірка всередині Page Object, яка підтверджує, що правильна page та її critical elements готові до operations; business assertions залишаються в test code.
Неймінг та структура automation-проєкту →Design pattern, який відділяє test code від page-specific locators і operations; UI change зазвичай локалізується в одному object.
Неймінг та структура automation-проєкту →Class name позначає page, methods описують actions, locators зберігаються в одному місці, а open завершується мінімальною readiness check.
Після open() test продовжується лише коли heading Sign in видимий; fill_email() приховує locator details від test code.
Login-сценарій переноситься до `LoginPage`: тест передає login і password, а Page Object виконує технічні дії з полями та кнопкою. Поширений варіант — передавати `WebDriver` у constructor кожного Page Object, але це повторює однакову залежність у тестах і сторінках. Для навчального врапера обирається централізований provider, з якого Page Objects отримуватимуть поточний драйвер без constructor plumbing. Водночас пакети розділяються за призначенням: web pages залишаються окремо від common-коду обгортки та від можливих API tests.
Замість довгого `locator.waitFor` для очікуваного стану використовується динамічний Playwright assertion на `Locator`, наприклад перевірка видимості або тексту. Так очікування і причина падіння залишаються частиною перевірки, а не окремим технічним кроком. Для `HomePage`, `SignInPage`, `ProjectsPage` і сторінки окремого проєкту створюються Page Object-и. Кожен отримує спільний `Page` через constructor, зберігає дії на своїй сторінці та повертає наступний Page Object там, де сценарій переходить далі. Початковий лінійний тест рефакториться у послідовність доменних дій: відкрити home page, увійти, знайти проєкт, відкрити його й перевірити title. Це прибирає locator-и з тесту та залишає у ньому читабельний користувацький сценарій.
Page Object визначається як клас, що описує логічну частину сторінки: цілу сторінку або окремий повторно використовуваний компонент. Для початкового варіанта кожна сторінка отримує окремий клас із діями, доступними користувачеві на ній. У `src/main/java` створюється окрема структура пакетів для вебчастини та сторінок. Після перенесення методу авторизації Selenide стає недоступним у production-коді, бо залежність оголошена через `testImplementation`; її змінюють на `implementation`, тоді як test runner залишається лише в тестовій області. Після синхронізації Gradle IntelliJ IDEA може додати потрібні імпорти через quick fix; невикористані імпорти потрібно регулярно прибирати.
Дії та динамічні очікування переносяться в Page Object у порядку, в якому їх викликає сценарій. Перевірку точного тексту можна інкапсулювати методом, що приймає очікуване значення і використовує Selenide `shouldHave`. Це дозволяє Selenide чекати, доки елемент набуде потрібного стану. Якщо перевірка потребує довільної логіки, наприклад порівняння кількості тест-кейсів із порогом, Page Object повертає текст або оброблене значення, а assertion залишається в тесті. TestNG не переносять до `src/main/java`; production-частина отримує дані зі сторінки, тест явно формулює очікування. Викладач рекомендує динамічні очікування там, де це можливо, замість одноразового читання нестабільного UI.
Щоб будувати виклики через крапку, метод Page Object замість `void` повертає поточний тип і завершується `return this`. Так `open()` може повернути `SignInPage`, після чого одразу викликається `loginUser(...)`. У відео цей стиль пов'язують із назвами fluent interface та chain of invocation; у заголовку уроку також використано Chain of responsibility. Повернення `this` зручне для послідовності дій у межах одного Page Object. Повертати з кожного методу наступну сторінку викладач не радить: довгі ланцюжки приховують переходи й ускладнюють code review. Допустимий локальний виняток — компонент або popup, який належить поточній сторінці й природно стає наступним об'єктом взаємодії. Спільні значення, потрібні кільком тестам, переносяться до наявного `BaseTest`, а не дублюються. Для них обирається найвужча достатня видимість, у прикладі — `protected` для класів-нащадків.
Щоб не створювати Page Object-и безпосередньо в кожному тесті, будується невеликий application facade. Він один раз приймає `Page`, створює `HomePage`, `SignInPage`, `ProjectsPage` та інші сторінки у правильному порядку й віддає їх тесту через короткі методи. Під час рефакторингу перевіряється момент ініціалізації: Page Object-и не можна створювати раніше, ніж JUnit integration надасть валідний `Page`. Після перенесення створення у constructor application object отримується стабільний lifecycle без повторюваних `new ...Page(page)` у тесті. У вбудованій Playwright JUnit implementation показано зберігання instances через `ThreadLocal`. Це дає окремі Playwright, Browser, BrowserContext і Page для кожного test thread; tracing lifecycle додатково враховує завершення, падіння або скасування тесту.
Першим джерелом назви сторінки є route: кореневий шлях підказує home page, а змістовний path — конкретний екран. Якщо це SPA або URL не змінюється, наступним джерелом стає видима назва сторінки: `h1`, `h2`, title чи інший семантичний заголовок. Коли framework генерує сторінку переважно з `div`, треба орієнтуватися на мову продукту та стабільні атрибути DOM. Мета — щоб назва в automation-коді відповідала тому, як екран уже називають користувачі й розробники.
Заняття підсумовує перехід від простого KISS-тесту, доповненого YAGNI, DRY і DAMP, до Page Object-структури з очікуваннями та двома способами перевірок: очікувати значення безпосередньо в об'єкті сторінки або повернути дані в тест для окремого порівняння. Для іменування класів, методів, змінних і тестів радять використовувати терміни, уже закладені розробниками: назви з URL, HTML та мережевих запитів, а також фактичні дії користувача. Наступні тести пропонується одразу писати через Page Object і вдосконалювати назви практикою.
На базовому рівні потрібно розуміти primitives/value types, reference/object types, класи, об'єкти та принципи OOP. Із прикладних патернів найчастіше зустрічається Page Object; корисно впізнавати Singleton, Builder, Facade та інші рішення, але не впроваджувати їх без проблеми, яку вони реально спрощують. Page Factory виник навколо старих Selenium-підходів із lazy initialization елементів. Для сучасного Selenium або Playwright його не варто застосовувати за інерцією. У багатопоточному WebDriver framework кожен тест/worker повинен мати власний browser context або driver; спільний mutable driver спричиняє взаємний вплив тестів.
Через `__init__` клас отримує залежності й початковий стан, без яких його методи не мають сенсу. Наприклад, компонент приймає кореневий locator, а Page Object — Playwright `page`; наступні методи перевикористовують ці значення через `self`. У повсякденній мові `__init__` часто називають constructor. Технічно екземпляр створює `__new__`, а `__init__` ініціалізує вже створений об’єкт. Для звичайного Page Object достатньо реалізувати саме `__init__`.