Надіслати запит Працюйте в Sii

У роботі тестувальника автоматизації одним з ключових завдань є коректна робота з очікуваннями подій, що дозволяє виконувати підтвердження на вже підготовленому елементі. У жаргоні тестувальників ми зустрічаємо термін «очікування» від методу wait(), і в цій статті використовується саме така номенклатура.

У цьому пості я розповім про те, для чого потрібні очікування в автоматизованих тестах, представлю порівняння очікувань, доступних в Selenium і Cypress, а також приклад реалізації в Cypress.

Cypress значно виділяється серед інших доступних додатків для автоматизованого тестування завдяки одному специфічному очікуванню, яке також буде описано разом з методами cy.wait() та cy.intercept(). Останнім аспектом, який обговорюватиметься у цій статті, буде рекурсія, яку також можна використовувати у Cypress для очікування елемента в якості його власного користувацького підходу.

Очікування в автоматизованих тестах

Очікування – одна з основних і ключових частин автоматизованого тесту. Вона дозволяє нам виконати затримку тесту, щоб правильно завантажити веб-сторінку або будь-який елемент на ній. Така опція дозволяє перевірити, до чого це призведе – до позитивного або негативного завершення тесту.

Неправильна реалізація функції Wait може призвести до неправильного результату тесту, наприклад, в разі спроби взаємодії зі сторінкою, яка не повністю завантажилася. Інша популярна проблема – невідображення елемента, оскільки він очікував, наприклад, на відповідь сервера. Однак одна з найбільших труднощів, пов’язаних з неправильною реалізацією очікування, – це зайве очікування, яке збільшує тривалість тесту.

Очікування в Selenium

В одному з найпопулярніших інструментів для автоматизації тестування – Selenium – ми зустрічаємося з трьома типами очікувань, які я опишу нижче.

Неявне очікування

Воно полягає у спробі знайти елемент у DOM, який не вдається знайти відразу, за певний проміжок часу. За замовчуванням значення цього очікування дорівнює 0, і коли ми змінюємо це значення, неявне очікування триває до кінця сеансу.

1 1 - Автоматизовані тести: Cypress чекає, поки... – вступ до очікування
Рис. 1 Приклад з Selenium – неявне очікування

Як показано в коді вище, реалізація цього рішення дуже швидка, але має деякі обмеження. Це очікування працює тільки з методом findElement(), що заважає нам дочекатися завантаження, наприклад, тексту в елементі.

Явне очікування

Завдяки йому ми маємо можливість зупинити тест, доки не буде виконано очікувану умову. Перевірка умови запускається з певною частотою, поки не закінчиться час очкування. Це означає, що якщо умова видасть хибне значення, Selenium зачекає і спробує ще раз.

2 1 - Автоматизовані тести: Cypress чекає, поки... – вступ до очікування
Рис. 2 Приклад з Selenium – неявне очікування

У наведеному вище коді ми чекаємо, поки заголовок нашої сторінки набере очікуваного значення. Майте на увазі, що очікування тепер використовується тільки в момент спрацьовування тригера, а не як раніше – глобально. Тут ви знайдете перелік доступних прогнозованих явних умов очікування для Selenium.

Ми явно чекаємо певної ситуації протягом заданої кількості секунд – наприклад, наступний код протягом 10 секунд буде перевіряти, чи має наш сайт очікуваний заголовок, з частотою в одну секунду.

3 1024x42 1 - Автоматизовані тести: Cypress чекає, поки... – вступ до очікування
Рис. 3 Приклад Selenium – FluentWait

Очікування в Cypress

Cypress за замовчуванням використовує динамічне очікування елементів або дій, доступних на веб-сторінці, що використовується в нашому автоматизованому тесті. Можна виділити наступні способи обробки очікувань.

Час очікування за замовчуванням

У Cypress доступно 6 значень часу очікування за замовчуванням. Завдяки вбудованому механізму повторних спроб вони виконують перевірку через визначений нами або попередньо встановлений час, подібно до описаного раніше явного очікування:

  • defaultCommandTimeout – час, за який Cypress намагається дістатися до елемента або дії під час виконання більшості команд на DOM.
  • execTimeout – час очікування, який визначає, як довго потрібно чекати, поки система завершить операції під час виконання команди cy.exec().
  • taskTimeout – максимальний час, протягом якого ми чекаємо на завершення завдання під час виконання команди cy.task().
  • pageLoadTimeout – очікує на «подію переходу на іншу сторінку». Ця подія відбувається тоді, коли користувач відвідує або залишає певну веб-сторінку. Цей час очікування за замовчуванням також очікує на команди cy.visit(), cy.go(), cy.reload(), які виконують події завантаження. Вони спрацьовують, коли завантажується вся сторінка і весь її вміст, тобто таблиця стилів, скрипти, iframe і зображення.
  • requestTimeout – максимальний час очікування виконання cy.wait().
  • responseTimeout – очікує виконання методів cy.request(), cy.wait(), cy.fixture(), cy.getCookie(), cy.getCookies(), cy.setCookie(), cy.clearCookie(), cy.clearCookies() та cy.screenshot().

Якщо ми хочемо замінити значення часу очікування, ми робимо це у файлі cypress.json:

4 - Автоматизовані тести: Cypress чекає, поки... – вступ до очікування
Рис. 4 Cypress – cypress.json встановлює значення defaultCommandTimeout

Ми також можемо змінити цей час для певного ланцюжка дій або самого методу, відправивши об’єкт з очікуваним часом:

5 - Автоматизовані тести: Cypress чекає, поки... – вступ до очікування
Рис. 5 Cypress – неявне використання суб’єкта та перезапис defaultCommandTimeout шляхом надсилання об’єкта до методу get

У наведеному вище коді ми використали неявний суб’єкт для створення підтвердження за допомогою методу .should(). Спочатку Cypress намагається знайти елемент button протягом 20 секунд, визначених в об’єкті sent {timeout: 20000}, а потім виконує підтвердження для цієї кнопки, щоб перевірити, чи містить вона текст «Search in Google». Тут, знову ж таки, програма чекає до 20 секунд на появу тексту. Ми можемо отримати час очікування під час виконання методів cy.get() і should(), що зведе нанівець весь тест.

Для методів get(), find(), cointains(), виходячи зі свого досвіду, я рекомендую використовувати час очікування на ланцюжку дій на випадок, якщо очікування елемента або його властивостей затягнеться. При цьому час очікування, встановлений в cypress.json, повинен бути обмежений розумним мінімумом, щоб уникнути невиправданого збільшення тривалості тестів у випадку, якщо ми отримаємо незадовільний результат.

У Cypress є можливість виконати подібне затвердження з явним суб’єктом, використовуючи метод .then() і виконуючи затвердження на елементі JQuery:

6 - Автоматизовані тести: Cypress чекає, поки... – вступ до очікування
Рис. 6 Приклад з Cypress – затвердження з явним суб’єктом

У цьому випадку Cypress спочатку чекає до 20 секунд на метод .get(), а потім одразу ж виконує затвердження на елементі, пропускаючи визначене значення defaultCommandTimeout.

Вбудована функція очікування

Cypress має власну реалізацію методу wait, який приймає до двох аргументів:

  • Одне з перших значень – це числове значення, подане в мілісекундах. Це значення часу, який минає між попередньою і наступною командою в ланцюжку дій Cypress.
  • Наступне значення, яке ми можемо відправити замість часу – це псевдонім або таблиця псевдонімів. Псевдоніми – це величезна конструкція в Cypress, яка має багато застосувань, і про неї можна написати окрему статтю. Однак, для нас, в концепції очікувань, найважливіше зосередитися на можливості призначити псевдонім виклику API. Ми робимо це за допомогою cy.intercept() і методу .as(), де метод as зберігає псевдонім, до якого ми маємо доступ за допомогою префікса @.
  • Останнє, необов’язкове, значення – це об’єкт option, який дозволяє нам перезаписати попередньо визначений час за замовчуванням для requestTimeout і responseTimeout. Крім того, це об’єкт {log: true/false}.
7 - Автоматизовані тести: Cypress чекає, поки... – вступ до очікування
Рис. 7 Cypress – способи реалізації cy.wait()

У цьому коді показано реалізацію методу очікування Cypress. Цей метод дозволяє нам чекати в певному місці коду протягом заданого періоду часу або поки не з’явиться відповідний псевдонім.

Створення псевдоніма

Щоб правильно створити очікування для псевдоніма, нам потрібен саме цей псевдонім. Одним з методів його створення є перегляд запитів, зроблених браузером на нашій тестовій сторінці. Потім ми вибираємо останній запит або кілька останніх запитів, які з високою ймовірністю покажуть нам, що сторінка завантажена.

8 - Автоматизовані тести: Cypress чекає, поки... – вступ до очікування
Рис. 8 Список запитів API на сторінці www.google.pl

Після того, як ми знайшли запит, який нас цікавить, все, що нам потрібно зробити, це використати метод cy.intercept(). Він дозволяє нам відстежувати запити і відповіді в мережі та керувати ними. Він дозволяє нам:

  • Імітувати дані
  • Перевіряти запити API
  • А завдяки комбінації з cy.wait(), дочекатися закінчення заданого запиту API.

Потім, за допомогою методу .as(), ми можемо зберегти відстежений запит як псевдонім.

Реалізація перехоплення

9 - Автоматизовані тести: Cypress чекає, поки... – вступ до очікування
Рис. 9 Приклад з Cypress – реалізація методу cy.intercept()

Реалізація перехоплення, яку ми згодом використаємо у тесті, наведена вище. Її завдання полягає в тому, щоб:

  1. Відвідати сторінку google.pl.
  2. Прийняти файли cookie.
  3. Ввести в рядок пошуку «Sii» і натиснути кнопку Enter.
  4. Дочекатися псевдоніма @finishedGoogleSearch.
  5. Перевірити, чи на завантаженій сторінці видно текст «Około».
10 - Автоматизовані тести: Cypress чекає, поки... – вступ до очікування
Рис. 10 Приклад з Cypress – тестовий код з використанням методу очікування на псевдонім

Я раджу уникати очікування протягом заданого часу і зосередитися на очікуванні псевдонімів. Це зробить наші тести коротшими, а код буде більш оптимізованим і в ньому буде значно менше неочікуваних винятків.

Одним з додаткових пакетів для ESLint є Cypress ESLint Plugin, який дозволяє визначити правило «cypress/no-unnecessary-waiting»: «error» і виявляти ці очікування під час створення автоматизованих тестів.

Реалізація користувацьких очікувань

Якщо нам потрібне спеціальне очікування, яке не відповідає описаним раніше параметрам cy.wait(), ми можемо використати рекурсивне очікування з перевіркою умови під час кожного звернення.

Рекурсія – це звернення функції або її самовизначення. Вона зустрічається в математиці (алгоритм Евкліда, послідовність Фібоначчі), програмуванні і навіть мистецтві (картина в картині або розміщення двох дзеркал навпроти один одного – саме тоді ми отримуємо відображення у відображенні).

Але повернімося до програмування і нашого прикладу. Ми хочемо написати функцію очікування, яка буде чекати, поки очікуваний елемент не з’явиться на сторінці.

11 - Автоматизовані тести: Cypress чекає, поки... – вступ до очікування
Рис. 11 Приклад з Cypress – реалізація рекурсивного очікування появи елемента

Функція очікування виконує це завдання у наступному порядку:

  1. Отримання вмісту тіла методом .get().
  2. Потім перетворення цього об’єкта на об’єкт JQuery, виклик на ньому методу .find(locator) і, нарешті, .length, який видає значення 0, якщо елемента немає в тілі.
  3. Очікування, розподілене в часі – це час, через який ми хочемо провести ще одну перевірку, чи відповідає елемент заданій умові.
  4. Визначаємо totalTime і з кожним наступним рекурсивним викликом починаємо збільшувати його на заданий час перерви (split).
  5. Перевіряємо, чи totalTime менше або дорівнює часу очікування. Залежно від результату умови, рекурсивно викликається функція checkForElement(), або cy.get(resultText), щоб скасувати перевірку.
  6. Нарешті, у випадку невиконання умови body.find(elementID).length === 0 викликаємо cy.get(resultsText), який закриває рекурсію.

Це не ідеальне рішення описаної проблеми, і його слід використовувати лише в крайньому випадку, оскільки ми маємо справу з труднощами зчитування коду та його підтримки.

Наведений вище код дуже важко виправляти в Cypress і некомпетентне використання рекурсії або циклів може призвести до потрапляння в нескінченний цикл. Існує ймовірність його виникнення в разі змішування синхронного та асинхронного коду або некоректного контролю умов інкрементування. Зрештою, нескінченний цикл призведе до помилки тестування і браузер перестане реагувати.

Доступні зовнішні пакети очікування

У цьому розділі я розповім про два відомі мені пакети, які ми можемо використати у наших тестах.

  • cypress-wait-until дозволяє чекати на все, чого не чекає метод cy.wait(). Метод cy.waitUntil() отримує два аргументи. Перший – це функція, яка виконує метод, методи або цілий ланцюжок дій Cypress. Наступний аргумент – об’єкт option, який дозволяє керувати часом очікування та інтервалом. Код намагається отримати доступ до поля браузера протягом трьох секунд з інтервалом в одну секунду. Редагуючи значення за замовчуванням, ми можемо вільно керувати значеннями часу очікування та інтервалу. Значення за замовчуванням для цього очікування: timeout=5000, interval=200.
12 1 - Автоматизовані тести: Cypress чекає, поки... – вступ до очікування
Рис. 12 Cypress – приклад реалізації cypress-wait-until

cypress-recurse як пакет забезпечує рекурсивне очікування, поки очікуваний код не видасть значення True. У цьому випадку очікуваною умовою є expect(button).to.have.value(‘Szukaj w Google’)}. Метод відкине тест, якщо протягом 30 секунд ця умова не видасть значення True. Сама умова буде перевірятися з частотою 0,5 секунди. Значення за замовчуванням для методу: timeout=4000, limit=15, delay=800.

13 - Автоматизовані тести: Cypress чекає, поки... – вступ до очікування
Рис. 13 Cypress – приклад коду cypress-рекурсу

Порівняння очікування в програмах Seleniumта Cypress

Оцінімо схожість між очікуванням в програмі Selenium і очікуванням в програмі Cypress.

Почнемо з неявного очікування. Подібну поведінку ми можемо спостерігати в Cypress – керуючи «defaultCommandTimeout» або самим часом очікування, ми можемо чекати на появу елемента на сторінці за допомогою методу cy.get() у вказаний нами час.

Явне очікування в Cypress є досить суперечливою темою, оскільки воно передбачає перевірку умови. Метод Cypress .should(‘be.visible’) можна розглядати як еквівалент очікуваної умови elementIsVisible(element) в Selenium. Однак: чи є підтвердження очікуванням? Якщо припустити, що так, то ми можемо розглядати всі підтвердження .should() як явне очікування. Я впевнений, що думки щодо цієї теорії розділилися, тому залишаю шукати відповідь на це питання вам самим 🙂

Не забуваймо про cy.wait(@alias). Саме це очікування можна вважати повноцінним явним очікуванням. Представлені зовнішні пакети cypress-wait-until-until та cypress-recurse ближче до явного, або навіть вільного очікування, завдяки можливості керувати інтервалом, через який перевіряється умова.

Підсумок

У цій статті я представив доступні способи очікування елементів в програмах Selenium і Cypress. Ці очікування дозволяють вільно працювати з більшістю елементів. Я представив різницю в часі з підтвердженнями Cypress. Я підготував приклад коду з власним очікуванням і розглянув два зовнішні пакети, з якими ми можемо працювати в Cypress, залежно від наших потреб.

Якщо ви лише починаєте знайомство з Cypress, варто з самого початку дізнатися про область cy.wait(‘@Alias’). Це базовий функціонал інструменту, який підвищує якість коду в наших автоматизованих тестах і позбавляє від необхідності чекати, поки елемент завантажиться. Успіхів!

Джерела

Оцінка:

Вам також може сподобатися

Більше статей

Отримайте пропозицію

Якщо у вас виникли запитання або ви хочете дізнатися більше про наші пропозиції, зв’яжіться з нами.

Надіслати запит Надіслати запит

Tomasz Ukraine Business Lead

Get an offer

Працюйте в Sii

Знайдіть роботу, яка підходить саме вам. Перевірте відкриті вакансії та подайте заявку.

Подати заявку Працюйте в Sii

Viktoriya Recruitment Specialist

Join Sii

SUBMIT

This content is available only in one language version.
You will be redirected to home page.

Are you sure you want to leave this page?