Конспект і таймкоди
0:00
Навіщо потрібні колекції елементів
Колекція потрібна, коли один конкретний елемент складно знайти напряму або коли однакову перевірку треба виконати для групи елементів. Практичний підхід — знайти всі відповідні елементи, відфільтрувати їх за критерієм і далі працювати з результатом.
Selenide за замовчуванням працює з колекцією динамічно: під час наступної перевірки він може знову виконати пошук за селектором, а не покладатися на раз назавжди зафіксований список DOM-вузлів. У демонстрації розглядаються варіанти пошуку всіх елементів, зокрема $$ і $$x; для XPath є окремий короткий запис.
Пошук колекції варто починати зі структури HTML: визначити контейнер і повторювані елементи на кшталт ul та li. Семантичні теги полегшують читання сторінки не лише тесту, а й accessibility-інструментам; якщо селектор неминуче неочевидний, йому дають предметну назву.
5:30
`ElementsCollection`, масиви та Java Collections Framework
Знайдені плитки проєктів зберігаються у змінній типу ElementsCollection — власному типі Selenide, пристосованому до роботи з набором UI-елементів. Поруч автор порівнює масиви з List і Set: колекції мають готові операції для обходу, фільтрації, пошуку, сортування, додавання та очищення.
Масив може бути трохи компактнішим або швидшим, але для UI-автотесту ця різниця зазвичай губиться на тлі звернень до браузера. Читання значення з пам’яті триває незрівнянно менше, ніж отримання тексту зі сторінки локально, у Jenkins або через BrowserStack. Тому для звичайних тестів важливіші зручність і читабельність; мікрооптимізації мають сенс лише після вимірювання реальної проблеми, наприклад коли підготовчі дії спотворюють performance test.
Для розміру масиву використовується length, а для колекції — метод size(). IDE підказує доступні операції та може запропонувати stream, але на цьому етапі урок радить залишатися з простішими колекційними API.
11:18
Примітиви, посилання в пам’яті та `toString()`
Локальна примітивна змінна на кшталт int і об’єкти або масиви мають різне представлення в пам’яті. Для масиву примітивів або посилальних типів змінна веде до області в heap; масив String містить посилання на окремі рядки.
Простий друк масиву не показує його елементи так само зручно, як друк колекції: для масиву в демонстрації потрібне явне перетворення через Arrays.toString(...). Коли об’єкт передається в System.out.println(...), Java неявно звертається до його toString().
Для маленького експерименту автор запускає окремий main, щоб не проходити весь UI-тест. При цьому test framework hooks, preconditions і postconditions не запускаються; якщо вони важливі для поведінки, перевірку потрібно залишити звичайним тестом.
17:14
Індексований `for` і enhanced `for`
Індексований for складається з початкового значення, умови завершення та кроку. Кожну частину можна змінити або винести, але цикл без умови завершення потребує явного break, інакше він не зупиниться.
Індекси масивів і колекцій починаються з нуля: перший елемент має індекс 0, а п’ятий — 4. Саме тому типова умова обходу порівнює індекс із розміром через <, не намагаючись звернутися до індексу, рівного довжині.
Enhanced for сам проходить усі значення й не потребує ручної роботи з індексом. Для більшості перевірок елементів це читабельніший варіант; індексований цикл потрібен, коли важлива позиція або нестандартний напрямок обходу.
21:19
`filter`, `find` і перенесення даних із UI в Java
filter залишає в результаті всі елементи, які відповідають Condition, і повертає нову ElementsCollection. find шукає перший відповідний елемент та повертає SelenideElement; в API також показані парні варіанти filterBy і findBy.
Якщо на сторінці треба перевірити десятки або сотні значень, багато окремих браузерних звернень можуть стати найдорожчою частиною тесту. У такому випадку доцільно один раз отримати потрібні тексти зі сторінки в Java collection і виконати решту перевірок у Java. Для одного елемента така оптимізація майже не дає користі й лише ускладнює тест.
25:07
`CollectionCondition` і timeout перевірок
Колекцію можна перевіряти через shouldHave(...) та умови з CollectionCondition. У демонстрації розглядаються перевірки розміру, sizeGreaterThan(...) і точних текстів. Перевірка списку текстів також звіряє кількість елементів, тому падає, якщо очікуваних значень менше, ніж реально знайдених.
Падіння прикладу показує стандартне очікування близько чотирьох секунд. Глобальний Configuration.timeout можна змінити, після чого непараметризовані should... чекатимуть новий час. Збільшувати його варто свідомо: це впливає на всі відповідні перевірки, а не лише на один повільний елемент.
30:45
Масова перевірка текстів колекції
Автор пробує зібрати великий список очікуваних текстів і передати його в одну перевірку, але такий запис стає громіздким і впирається в обмеження обраного способу створення списку. Практичніший варіант у демонстрації — пройти всі знайдені елементи та для кожного перевірити одну з дозволених умов.
Для альтернативних текстів використовується складена умова через Condition.or(...): кожен елемент має містити один із допустимих варіантів. Такий обхід зберігає предметне правило в тесті й дає змогу перевіряти кожен UI-елемент окремо.
37:44
Пошук за селектором або текстом і межі chaining
Одна стратегія спочатку знаходить елементи за структурним селектором, а потім перевіряє їхній текст. Інша одразу знаходить елементи за текстом і перевіряє розмір отриманої колекції. У виміряному прикладі прямий пошук за текстом із перевіркою розміру виявився швидшим за фільтрацію вже знайденої колекції, але автор радить вибирати підхід за конкретною сторінкою та власними вимірами.
Після пошуку одного контейнера можна знайти всередині нього колекцію. Зворотний chaining — отримати колекцію через $$, а потім одразу застосувати пошук одного дочірнього елемента до всієї колекції — не працює як пошук у кожному елементі. Для цього треба пройти колекцію циклом і виконати дочірній пошук для кожного SelenideElement.
42:59
Примітивні та wrapper types
Серед часто вживаних примітивів названо int, boolean, double, float, byte і long. byte стане потрібним під час роботи з файлами; для чисел із дробовою частиною або складніших числових операцій автор радить звернути увагу на BigDecimal, а не покладатися лише на примітиви.
Wrapper classes на кшталт Integer надають методи, яких немає у примітивного int. Урок не забороняє примітиви: з ними варто поекспериментувати, але коли логіка навколо значення зростає, посилальний тип може бути зручнішим. while і do-while відкладаються до теми роботи з файлами.
46:00
Огляд умов для колекцій через IDE
У CollectionCondition є різні очікування для розміру й текстів, зокрема exact/case-sensitive варіанти та перевірки текстів без залежності від порядку. Не потрібно запам’ятовувати весь перелік: у IntelliJ IDEA можна перейти до declaration або відкрити quick documentation клавішею F1 і прочитати точний контракт.
Для дуже великої колекції одна масивна декларація очікуваних текстів незручна. Краще вибрати конкретне правило, отримати потрібні значення або перевіряти елементи по одному, ніж уміщувати всі можливі assertions в один виклик.
48:35
Робота з clipboard у Selenide
Clipboard API корисний для застосунків, які копіюють значення з UI або приймають неструктурований текст із буфера. Як приклад наведено платіжний сценарій: застосунок може витягнути IBAN, суму та інші реквізити з великого повідомлення.
У демонстрації текст записується в clipboard, потім читається назад і перевіряється на еквівалентність. Для UI-сценарію той самий підхід дає змогу натиснути Copy й підтвердити фактичний вміст буфера через clipboard condition, а не лише факт кліку.
Selenide дає змогу читати, додавати, видаляти й очищати значення localStorage. Це корисно, коли ключ перемикає тестовий режим застосунку або коли тест має перевірити, що введені користувачем дані збереглися між переходами.
Приклад із checkout: користувач вводить дані, повертається на попередню сторінку, а застосунок відновлює їх із localStorage. Замість ручного отримання всього storage і загального assertEquals можна використати умову на конкретний item та його value.
53:39
`WebDriverConditions` і перевірки URL
Умови WebDriver дозволяють перевіряти URL, title, cookies та інший стан браузера. Автор застерігає від беззмістовної перевірки випадкового фрагмента URL: вона подібна до перевірки елемента лише за індексом і не доводить, що користувач отримав потрібний результат.
URL-condition виправданий для redirects або query parameters із предметним значенням — наприклад, коли треба підтвердити джерело переходу з Google, Hotline, соціальної мережі чи іншого метапошуку. В інших випадках краще чекати спостережуваний стан сторінки через предметний isLoaded-метод.
55:35
Оновлення бібліотек і домашнє завдання
Release notes бібліотек варто читати не лише заради нових API: пояснення змін часто показує обмеження старої поведінки, причини перенесення функціоналу та deprecated можливості. Для clipboard і localStorage достатньо самостійно відкрити документацію та зробити короткі експерименти на навчальному сайті.
Головне завдання — попрактикуватися з колекціями елементів і порівняти підходи на власному прикладі. Окрема домашня робота — прочитати про ієрархію Java Collections Framework; у повсякденних тестах найчастіше знадобляться ArrayList і Map.