Ефективні UI-тести на Selenide

В очікуванні чудес

Переддень Нового Року — час чудес. Напередодні нового року ми всі згадуємо рік, що минає, і будуємо плани на наступний. І сподіваємося, що всі проблеми залишаться у минулому, а в новому році станеться чудо, і ми заживемо по-новому.

Який же Java розробник не мріє про диво, яке осяє його і дозволить стати найкрутішим На Світі Java Програмістом.

Хороші новини: я хочу розповісти саме про таке диво.

Ім'я йому — автоматичні тести!


Фу, тести?

Так. Справжнім майстром своєї справи вас не зроблять диво-фреймворки, не мікро/піко/нано сервіси, а дисципліна. Дисципліна, яка говорить, що програміст може вважати справу завершеним не тоді, коли код готовий, а тоді, коли до нього написані і запущені автоматичні тести. І якщо з юніт-тестами все більш-менш ясно, то UI-тести поки залишаються для розробників темним лісом.

Та ну, це ж нудно?

О ні, повірте мені! Написання грамотних автотестів — це гарний виклик, тут є над чим розкинути мізками. І це може бути дуже весело і цікаво. Тільки треба використовувати правильні інструменти.

Правильний інструмент для написання UI-тестів — це:

Selenide

Selenide — це бібліотека для написання лаконічних і стабільних UI тестів з відкритим вихідним кодом.

Selenide — ідеальний вибір для розробників, тому що у неї дуже низька крива навчання. Вам не доведеться морочитися з усіма цими технічними подробиць, на які зазвичай тестувальники-автоматизаторы витрачають так багато часу: нюанси роботи з браузерами, типові проблеми з таймінгом та аяксом.

Подивимося, як виглядає простенький тест на Selenide:

public class GoogleTest {
@Test
public void user_can_search_everything_in_google() {
open("http://google.com/ncr");
$(By.name("q")).val("selenide").pressEnter();

$$("#ires .g").shouldHave(size(10));

$("#ires .g").shouldBe(visible).shouldHave(
text("Selenide: concise UI tests in Java"),
text("selenide.org"));
}
}


(природно, замість Google тут буде ваше веб-додаток)

Що тут відбувається?

  • Ви відкриваєте браузер всього лише однією командою open(url)
  • Ви шукаєте елемент на сторінці командою $.
    Ви можете знайти елемент по імені, ID, CSS селектору, атрибуту, xpath, і навіть за текстом.
  • Ви робите якісь дії з елементом: в даному випадку вводите текст командою val() і натискаєте enter допомогою команди pressEnter().
  • Ви перевіряєте результат: шукаєте всі результати пошуку за допомогою $$ (вона повертає колекцію елементів). Ви перевіряєте розмір і вміст колекції.


Цей тест легко читається, не чи правда?
Цей тест легко пишеться, чи не правда?

А головне, цей тест легко запускається. Переконайтеся самі:


глибше Занурюємося

Звичайно, в житті не все так просто. Написання автотестів увазі купу проблем, адже не дарма розробники так їх бояться більше, ніж будь-якого наисложнейшего фреймворку або технології.

Але і тут Selenide полегшує наше життя, вирішуючи більшість цих проблем з коробки.

Давайте розглянемо типові проблеми UI-тестів докладніше.

Проблеми з аяксом і таймаутами
У наш час веб-додатки всі суцільно динамічні. Кожен шматочок програми може бути намальований/змінено динамічно в будь-який момент часу. Це створює проблеми для автоматичних тестів. Тест, який ще вчора був зеленим, може раптово стати червоним без будь-яких змін в коді. Просто тому, що браузер сьогодні встав не з тієї ноги і запустив он той javascript трішки повільніше, і тест встиг натиснути кнопочку раніше, ніж вона до кінця отрисовалась.

Це прям вічна проблема у всіх. Тому автоматизаторы пхають скрізь «сліпи».

Тим більше дивно, наскільки простим і надійним способом Selenide вирішує цю проблему.

Якщо коротко, в Selenide кожен метод вміє трошки почекати, якщо треба. Люди називають це «розумними очікуваннями».

Коли ви пишете
$("#menu").shouldHave(text("Привіт"));

Selenide перевірить, чи є елемент з ID=«menu». І якщо ні, Selenide трохи почекає, перевірить ще. Потім ще почекає. І тільки коли елемент з'явиться, Selenide перевірить, що у нього потрібний текст.

Звичайно, не можна чекати вічно. Тому Selenide чекає не більше 4 секунд. Природно, цей таймаут можна настроювати.

Не зробить це мої тести повільними?
Ні, не зробить. Selenide чекає, тільки якщо треба. Якщо елемент споконвічно присутня на сторінці — Selenide не чекає. Якщо елемент з'явився через 300 мс — Selenide чекає тільки 300 мс. Це саме те, що вам потрібно.

Безліч вбудованих перевірок
А що ще ви можете перевіряти на сторінці, крім тексту? Досить багато всього.

Наприклад, ви можете перевірити, що видимий елемент (visible). Якщо поки ні, Selenide почекає до 4 секунд.
$(".loading_progress").shouldBe(visible);


Ви можете навіть перевірити, що елемент не існує. Якщо елемент все-таки знайдений, Selenide припустить, що він ось-ось зникне і почекає до 4 секунд.
$(By.name("gender")).should(disappear);


Ви можете робити кілька перевірок в одному рядку (т. зв. «fluent API» і «method chain»), що зробить ваші тести ще більш лаконічними:
$("#menu")
.shouldHave(text("Привіт"), text("John!"))
.shouldBe(enabled, selected);


Колекції
Selenide дозволяє вам дуже зручно працювати з колекціями елементів. Ви можете перевіряти відразу безліч елементів в одному рядку.

Наприклад, ви можете перевірити, що на сторінці рівно N таких елементів:
$$(".error").shouldHave(size(3));


Ви можете відфільтрувати підмножина елементів:
$$("#employees tbody tr")
.filter(visible)
.shouldHave(size(4));


Ви можете перевірити тексти елементів. У більшості випадків цього достатньо, щоб перевірити цілу таблицю або рядок в таблиці:
$$("#employees tbody tr").shouldHave(
texts(
"John Belushi",
"Bruce Willis",
"John Malkovich"
)
);


Скачування/закачування файлів
З Selenide закачувати файли гранично просто:
$("#cv").uploadFile(new File("cv.doc"));


Ви навіть можете завантажити декілька файлів разом:
$("#cv").uploadFile(
new File("cv1.doc"),
new File("cv2.doc"),
new File("cv3.doc")
);


І скачування файлів теж вкрай просто:
pdf File = $(".btn#cv").download);


Тестування «динамічних веб-додатків
Деякі веб-фреймворки (такі як GWT) генерують абсолютно нечитаний HTML, не піддається аналізу. Там немає постійних ID, імен або класів.

Це прям вічна проблема у всіх. Тому автоматизаторы пхають скрізь довжелезні «xpath і змушені їх підтримувати до кінця життя.

Щоб вирішити цю проблему, Selenide пропонує шукати елементи тексту.

import static com.codeborne.selenide.Selectors.*;

$(byText("Привіт, хабр!")) // знаходить елемент по тексту цілком
.shouldBe(visible);

$(withText("центр")) // знаходить елемент по підрядку
.shouldHave(text("Привіт, хабр!"));


Всупереч поширеній думці, пошук елементів по тексту — не така вже й погана ідея. Між іншим, саме так шукає елементи реальний користувач. Він не шукає елементи ID або класу, і вже тим більше не за XPATH. Він шукає по тексту. (ну, ще за кольором, але це важче піддається автоматизації).

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

$("td").parent()
$("td").closest("tr")
$(".btn").closest(".modal")
$("div").find(By.name("q"))


Наприклад, ви можете знайти комірку в таблиці по тексту, потім знайти містить її рядок tr і знайти в цьому рядку кнопку «Save»:
$("table#employees")
.find(byText("Joshua"))
.closest("tr.employee")
.find(byValue("Save"))
.click();


Page Object


Коли один і той же елемент або сторінка використовується в багатьох тестах, має сенс винести логіку сторінки в окремий клас. Такий клас називається Page Object, і їх теж дуже зручно робити з Selenide.

Наведений вище приклад гугла можна переробити на page object таким чином:

@Test
public void userCanSearch() {
GooglePage page = open("http://google.com/ncr", GooglePage.class);
SearchResultsPage results = page.searchFor("selenide");
results.getResults().shouldHave(size(10));
results.getResult(0).shouldHave(text("Selenide: concise UI tests in Java"));
}

Page Object сторінки пошуку гугл:

public class GooglePage {
public SearchResultsPage searchFor(String text) {
$(By.name("q")).val(text).pressEnter();
return page(SearchResultsPage.class);
}
}

І для сторінку результатів пошуку:

public class SearchResultsPage {
public ElementsCollection getResults() {
return $$("#ires .g");
}
public SelenideElement getResult(int index) {
return $("#ires .g", index);
}
}


Але не зловживайте педж об'єктами.Хочу звернути вашу увагу, що UI-тестів має бути мало. З тієї простої причини, що це все-таки браузер,
аякс, javascript, а все це порівняно повільно і нестабільно. Напишіть один-два UI-тесту, які перевірять, що
додаток в цілому працює: сторінка відкривається, текст отрісовиваємих, кнопки натискаються, JavaScript не тарахкається.

А всілякі комбінації і рідкісні випадки обов'язково перевіряйте за допомогою модульних тестів.

Типова помилка — перевіряти все через UI. Цим особливо страждають тестувальники в тих компаніях, де розробники не пишуть
модульних тестів. Бідним тестувальникам просто нічого не залишається, крім як городити величезну неповоротку купу повільних
і нестабільних UI-тестів і впрягатися в їх довічну підтримку.

Але ти ж програміст! Не змушуй людей мучитися.


… і багато інших полезняшек
У Selenide є ще багато функцій, таких як:

$("div").scrollTo();
$("div").innerText();
$("div").innerHtml();
$("div").exists();
$("select").isImage();
$("select").getSelectedText();
$("select").getSelectedValue();
$("div").doubleClick();
$("div").contextClick();
$("div").hover();
$("div").dragAndDrop()
zoom(2.5);
і т. д.


Хороша новина в тому, що вам не потрібно все це запам'ятовувати. Просто наберіть $, точку і почніть писати приблизно, що ви хочете. Наприклад «val» або «enter». І подивіться, які варіанти запропонує ваша IDE.

Використовуйте міць IDE! Не засмічуйте голову деталями і сконцентруйтеся на бізнес-логікою.

image

Зробимо світ кращим

У вірю, що світ стане кращим, коли всі розробники будуть писати автоматичні тести для свого коду. Коли розробники будуть спокійно вставати о 17:00 і йти до своїх дітей, не боячись, що вони щось зламали своїми змінами.

Повірте мені, я відчуваю себе впевнено тому, що поки я ходив за кавою, мої тести вже перевірили мій код. І я точно знаю, що те, що я здаю в тестування — працює.

Давайте зробимо світ краще з допомогою автоматичних тестів! Будьте впевнені у своєму софті, і вам не доведеться схрещувати пальці на удачу перед кожним релізом.

selenide-logo
З Новим Роком!
ru.selenide.org

Джерело: Хабрахабр

0 коментарів

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