Як Clojure допомагає прискорити написання Selenium-тестів

imageПривіт, читачу! Якщо доводилося писати Selenuim-тести трохи складніше ніж на пару полів введення і одну кнопку, то ця стаття може стати в нагоді.
Напевно знайоме почуття неправильності того, що відбувається, коли раптово відмовлявся працювати тест-кейс довжиною в пару хвилин, змушуючи тыкаться наосліп, щоб знайти поламаний css — або xpath-селектор в складному Single Page Application, раз за разом запускаючи цей повільний сценарій, тільки щоб дочекатися висновку лода в консоль. Виявляється, можна писати Selenium-тести з комфортом!
Про що стаття — іншими словами, для нубовПро Selenium. Колись це був просто плагін для FireFox. Натискаєш кнопочку "запис", і починаєш смикати інтерфейси досліджуваного сайту (формочки, посилання). Практично без знання програмування, отриманий сценарій можна правити, підставляючи потрібні значення перевірок. Все — тест готовий! Запускай кожен раз після деплоя, та перевіряй, чого здвигнув ліктем. Потім в Selenium додали API для різних мов. Зокрема є і для JAVA. Через API можна робити теж саме: запускати браузер з необхідним сайтом, перевіряти передані значення у формах, ходити по посиланнях і т. д. Біда в тому, що скрипт виконується повільно. Щоб тестувати тести, треба перезапускати сценарій, а це формений катування. Clojure (поверх JAVA) дозволяє виконувати шматки коду в працюючій програмі за допомогою REPL прямо в редакторі!

Розбір проекту з Selenium-тестами

Проект доступний на GitHub, особливості:
  • Кросплатформеність — писати тести можна під ОС Windows, з профайлом +windows, потім збирати jar файл під *nix, і викладати на сервер.
  • Робота відразу з двома web drivers: selenium і phantom, це зручно коли потрібно візуально налагодити тест в Selenium, скомпілювати jar, який працює з Phantom і залити його на Linux-сервер де його буде смикати який-небудь CI-скрипт.
В залежностях проекту можна побачити бібліотеку — clj-webdriver, це основний інструмент для роботи з веб-драйвером, документація до нього.
Розберемо простий тест example-selenium-project.tests.gosuslugi-main:
(deftest gosuslugi-main-search-form
(profile/open-browser "https://www.gosuslugi.ru/")
(try
(->> ($ ".index-slider-search input")
(type-text "закордонний паспорт")
(->>keys Keys/ARROW_DOWN)
(->>keys Keys/ARROW_DOWN)
(->>keys Keys/ENTER))

(when-not ($ ".title_search")
(throw (Exception. "redirect to search result, error")))

(swap! profile/tests-success inc)
(is true)
(log/info "gosuslugi-main-search-form -> ok")

(catch Exception e
(log/info "gosuslugi-main-search-form -> fail" (.getMessage e))
(swap! profile/tests-fail inc)
(is false))))

(deftest gosuslugi-main-search-form ...)

deftest
— макрос, імпортується з бібліотеки
clojure.test
. Це вбудована в Clojure бібліотека для написання тестів. Має стандартний для тестів функціонал. Макрос
deftest
просто створює функцію.
Сам тест обгорнутий в
(try ... catch)
для зручності, щоб не переривати виконання форми викликом
Exception
, або ж у будь-яких нестандартних випадках (наприклад, якщо не знайдений елемент), і виконувати форму
catch
, обробну провал тесту.
(->> ($ ".index-slider-search input") ...)

->>
— стандартний Clojure-макрос для написання більш читабельного коду "шиворіт навиворіт". Без нього сценарій виглядав би так:
(->>keys Keys/ENTER
(->>keys Keys/ARROW_DOWN
(->>keys Keys/ARROW_DOWN 
(type-text "закордонний паспорт" ($ ".index-slider-search input")))))

Макрос
->>
приймає список форм і розкриває їх, передаючи послідовно результат виконання, як останній аргумент, наступної форми. Щоб використовувати макрос
->>
, я зробив кілька функцій-обгорток, які слідують простому угоди — приймають останнім елементом об'єкт element, і повертають його ж.
(swap! profile/tests-success inc)
та
(swap! profile/tests-fail inc)
— прості лічильники успішних і провалених тестів.

Чому Clojure?

Проста відповідь — рівень абстракції над складністю. Повинно бути ти вже сходив у Вікіпедію, подивився на синтаксис цього Lisp-діалекту, і проходиш першу стадію прийняття неминучого. Пройдеш її чи ні — справа твоє, можу дати кілька порад, заснованих на досвіді.
  • Clojure — легкий у вивченні мову, більш високий поріг входу пов'язаний з його відмінністю від імперативного підходу, який нам вбивають у голову зі школи. Переборовши закостенілість свідомості, ми побачимо що Clojure перетворюється на зручний інструмент, що дозволяє спростити розробку програми.
  • Як же не заплутатися в такому достатку дужок? Особливих проблем з дужками немає, до них звикаєш за день, коли розумієш їх призначення. Так само в редакторах з'явився ряд хороших інструментів, які полегшують інкубаційний період Clojure-розробника. По-перше, прекрасний Parinfer, доступний для більшості редакторів. А по-друге, банальне включення у налаштуваннях редактора райдужних дужок.
  • Для написання тестів не знадобиться досконале знання Clojure. Трансд'сер, редьюсеры та інша муть — вивчення цього можна відкласти на потім. Для старту досить освоїти базові речі за пару-трійку вечорів.
Як Parinfer допомагає закривати дужки в залежності від відступів

Швидкий старт з інструментів розробки

якби ти провів молодість будучи хіпі в Америці 60-х років, то міг відчути дух свободи, демократії і легких наркотиків; якщо не довелося, нічого страшного — цей дух ти можеш відчути використовуючи в роботі REPL Clojure.
REPL Clojure — виводить написання Selenium-тестів на зовсім інший рівень! Ключова особливість цього REPL від будь-яких інших в тому, що можна писати код на вже працюючому додатку, не втрачаючи його станів. Цей інструмент дозволяє не просто складати робочі css — або xpath-селектори, але і проводити тести в якому завгодно порядку, і перевіряти працездатність будь-якого з вузлів великого тест-кейсу не втрачаючи стану складного Single Page Application.
Демонстрація можливостей REPL в редакторі Atom
Виконання коду нашого проекту порядково допомогою REPL в редакторі LightTable
Редактор коду для Clojure — майже під всі популярні редактори і IDE існують плагіни для підтримки Clojure, я зупинився на IntelliJ IDEA + Cursive, як має найменш низький поріг входу. Невелика інструкція налаштування і використання REPL в Cursive.
Також популярні:
Leingen — менеджер залежностей, як npm зі світу Node.js. З тією відмінністю, що, як залежність, Leingen підносить ще й сам інтерпретатор Clojure. Тому нам досить буде встановити Leingen, Clojure він завантажить сам.
Про бібліотекиОсновна репозиторій Clojure, так само можна використовувати бібліотеки з maven-репозиторію (незліченні багатства Java-спільноти). Добірка корисних бібліотек.
Після цього можна створити новий Clojure-проект, набравши в консолі:
lein new app example-selenium-project

Leingen створить нам все дерево проекту і конфігураційний файл — project.clj, (npm його аналог — package.json).
Також в Leingen дуже добре реалізована робота з профайлами, визначивши ряд своїх профайлів у розділі
:profiles
file project.clj, можна дуже гнучко розділяти роботу програми в оточеннях develop або production, і не тільки.
Можна запустити додаток з будь-якою кількістю профайлів, наприклад:
lein with-profile +windows+selenium run

Або скомпілювати jar з потрібними профайлами:
lein with-profile +windows+phantom uberjar

Висновок

Ризикну припустити що Clojure є на сьогодні найбільш зручним інструментом для написання Selenium-тестів. Завдяки двом факторам: інтерактивного REPL і макросів, які дозволяють створити свій власний лаконічний DSL-підпроект. Як показує практика, можна не знати сама мова Clojure і успішно працювати з DSL на фасаді. Це відкриває непогані можливості до швидкого підключення нових фахівців до написання та підтримку тестів.

Корисні посилання

Критика статті в Slack-чатике #clojure-russiayashaka
у мене є підозри що за трай кетч в тест логіці можуть не слабо накинутися… будь-які складні конструкції типу ифов, циклів, трай кетчов — вважаються поганим тоном в написанні тестів
у нашому прикладі — це функціонал логування по суті, і такі речі зазвичай виносять в якісь абстракції...
може, якщо є бажання показати зручність, то варто показати як винести такий код логування в якусь — то функцію толі макрос додатковий навколо deftest
seryh
ну юніт тести і селениум тести, різні речі. на практиці try в селениуме дуже зручний. так як майже всі отваливания тестів відбуваються із-за застарілих селекторів (edited) або ще якоїсь раптової фігні яку складно передбачити
yashaka
логіка «не використовувати складні конструкції» зростає від того факту, що багато тестів, вони можуть змінюватись, і їх пише велику кількість людей, тому немає часу сильно вдумуватися в флоу — тести повинні бути буквально очевидними
по крайней мене, наскільки я це розумію:)
у селениум тестах — це ще більш важливо, так як тести складніше самі по собі...
seryh
так простір для поліпшення великий ) руки поки не дійшли
yashaka
або ще якоїсь раптової фігні яку складно передбачити
раптова фігня — це в будь-якому випадку эксепшен
і полетів эксепшен — це вже впав тест з репортів
просто вбудовані в селениум эксепшены — мало інформативні
тому люди і пишуть свої врапперы навколо селениума
як б тому — що б тест логіка залишалася простою і очевидною...
seryh
я там в статті зазначив у висновку що можна dsl написати простий
а в прикладі, так наколенная виріб
yashaka
я сам автоматизатор, а не розробник, і вишу тут в чатах на цю тему,
і там як тільки якийсь новачок показує тест з ифами і трай кетчами — відразу ллються гори моралей…
тут суть не в тому що добре а що погано…
а в тому що і так у нас посил гучний як для неформального мови, і народ почне лити критику :)
і виходить, що ми їм з нашими «наколенными підробками» тільки ще більше підстав даємо
У мене зараз завал, тому нажаль немає часу на те що б допомогти… Але якщо ми не поспішаємо, то десь через тиждень-другий, я зміг би поконтрибьютить в цю статтю...
motor4ik
а кейс найголовніший не розглянуто в статті? що впав тест та як його реплом полагодити?
я так розумію це була киллерфича статті немає?
seryh
публікація на понеділок запланована. взагалі якщо злетить то можна і другу статтю запив
і свій dsl для тестування запив =Р
а так, невеликий приклад зараз, цілком зрозумілий новачкові
P. S. Я виступаю лише в ролі натхненника і редактора, автор статті — seryh.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.