Вышла Selenide 5.15.0

Вышла Selenide 5.15.0

Обкликайся и обкачайся
26.09.20

Всем привет!

Мы выпустили релиз Selenide 5.15.0.

Добавили настройку Configuration.pageLoadTimeout
(по умолчанию 30 секунд)

Бывает так, что вебдрайвер надолго подвисает, пытаясь загрузить какую-то страницу, либо картинку на этой странице, или ещё какой-то элемент. Теряется время, сессия обрывается по таймауту и т.д.

В этом случае хорошо бы прервать тест пораньше, но таймаут для загрузки страницы в Selenium по умолчанию слишком большой: 5 минут.

Поэтому мы добавили в Selenide настройку Configuration.pageLoadTimeout, чтобы этот таймаут было легко менять.

Внимание! Значение по умолчанию - 30 секунд. Если ваши тесты начали падать по таймауту - знайте, какую настройку подкрутить.

См. issue 1268 и PR 1269.

Добавили универсальный метод клика
с параметром ClickOptions

В некотором роде это новое слово в API селенида.

В селениде изначально был метод $.click(), который просто вызывал обычный селениумовский метод WebElement.click(). Который кликает (вроде как) в центр элемента.

Со временем начали появляться вариации:

  • Настройка Configuration.clickViaJs, чтобы кликать не вызовом WebElement.click(), а через JavaScript. Теоретически это должно сделать тесты стабильнее (а может, и быстрее) и позволит кликать то, что обычно не получается.
  • Клик со сдвигом $.click(offsetX, offsetY), чтобы кликать не в центр элемента

Неудобно в этом то, что невозможно кликать то через JS, то через селениум - настройка глобальная. Пришлось бы её постоянно менять.

Поэтому мы добавили метод, в который можно явно передавать парметр - способ клика.

Теперь кликать можно без изменения глобальной настройки, хоть обкликайся:

  $("#page").click(usingJavaScript());
  $("#page").click(usingJavaScript().offset(123, 222));
  $("#page").click(usingJavaScript().offsetY(222));
  $("#page").click(usingDefaultMethod());

NB! Мы рекомендуем выставить настройку Configuration.clickViaJs в то значение, которое вам подходит в большинстве случаев, и задавать параметр ClickOptions точечно - только там, где он необходим.

См. issue 1173.
Спасибо Dmytro Stekanov за PR 1226.

Добавили универсальный метод скачивания файла
с параметром DownloadOptions

Аналогичная история была с методом $.download(). Изначально он умел скачивать файлы только одним способом - через GET запрос. Потом селенид научился скачивать файлы через прокси. Недавно мы добавили третий способ - FOLDER.
До сих пор способ скачивания можно было задать только через глобальную настройку Configuration.fileDownload.

А теперь способ скачивания можно задавать через параметр в каждый вызов $.download, не меняя глобальную настройку:

  File f = $("input").download(DownloadOptions.using(PROXY);
  File f = $("input").download(DownloadOptions.using(PROXY).withTimeout(9999));
  File f = $("input").download(DownloadOptions.using(PROXY).withFilter(withExtension("xls")).withTimeout(9999));
  File f = $("input").download(DownloadOptions.using(FOLDER);
  File f = $("input").download(DownloadOptions.using(FOLDER).withTimeout(9999));
  File f = $("input").download(DownloadOptions.using(FOLDER).withFilter(withExtension("pdf")).withTimeout(9999));

NB! Мы рекомендуем выставить настройку Configuration.fileDownload в то значение, которое вам подходит в большинстве случаев, и задавать параметр DownloadsOptions точечно - только там, где он необходим.

См. issue 1259 и PR 1260.

Добавили методы для работы с LocalStorage

import static com.codeborne.selenide.Selenide.localStorage;

// Очистить всё содержимое:
localStorage().clear();

// Добавить значение:
localStorage().setItem("username", "john");

// Проверить значение:
assertThat(localStorage().getItem("username")).isEqualTo("john");

// Проверить количество элементов:
assertThat(localStorage().size()).isEqualTo(1);

// удалить значение:
localStorage().removeItem("username");
assertThat(localStorage().getItem("username")).isNull();

Спасибо Dmytro Stekanov за PR 1274.

Добавили проверки для текст элемента без потомков

Классическая селенидовская проверка $.shouldHave(text("Hello, world")) включает и текст самого элемента, и тексты всех его потомков.
А иногда хочется проверить только текст самого элемента, без потомков. Для этого мы добавила две новых проверки:

  $.shouldHave(ownText("Hello"));           // Элемент должен содержать текст "Hello"
  $.shouldHave(exactOwnText("Hello"));      // Текст элемента должен быть "Hello" 

См. issue 1261 и PR 1262.

Ускорили работу с большими фильтрованными коллекциями

В селениде есть удобные методы для работы с коллекциями элементов: их можно удобно отфильтровать, в них можно искать элементы или разом проверить, скажем, тексты всех элементов.

Но если слишком злоупотреблять, можно написать слишком медленный тест. Например, вот так:

ElementsCollection list = $$("li").filter(visible);   // На странице 100 элементов <li>
for (int i = 0; i < 10; i++) {
  list.get(i).shouldBe(visible);
}

Если на странице, предположим, 100 элементов <li>, то такой тест может очень долго работать.

  • Ведь селенид на каждом шагу должен перегрузить элемент - вдруг его состояние изменилось!
  • А чтобы перегрузить N-ный элемент коллекции, нужно перегрузить всю коллекцию (в селениуме ведь нет метода WebDriver.findElement(index)).
  • А чтобы перегрузить фильтрованную коллекцию, нужно пройтись по всем её элементам и применить фильтр для каждого (в данном примере - вызвать WebElement.isDisplayed()).


Для сравнения, такой цикл работает гораздо быстрее:

ElementsCollection unfiltered = $$("li");   // Нефльтрованная коллекция 
for (int i = 0; i < 10; i++) {
  unfiltered.get(i).shouldBe(visible);
}

В этом релизе мы немного ускорили работу с коллекциями. Теперь Селенид фильтрует коллекцию умнее: чтобы получить list.get(N), он применяет фильтр visible не для всех 100 элементов, а только для первых <N> элементов.

См. issue 1266 и PR 1270.


P.S. Напомню, что другой вариант ускорить тесты в таких случаях - использовать метод snapshot:

ElementsCollection list = $$("li").filter(visible).snapshot(); // snapshot() создаёт "слепок" коллекции. Селенид не будет её перегружать каждый раз. 
for (int i = 0; i < 10; i++) {
  list.get(i).shouldBe(visible);
}

Но при использовании snapshot есть риск словить StaleElementReferenceException, если коллекция всё-таки обновилась во время цикла.

Добавили проверку “href”

Иногда хочется в тесте проверить, что у элемента <a> правильное значение атрибута href, т.е. ссылки.
Для этого всегда можно было использовать метод $("a").shouldHave(attribute("href", "/foo/bar/details.html").

Проблема в том, что такая проверка очень неочевидно падает, потому что селениум возвращает абсолютный, а не относительный URL.
Подробнее см. в докладе Алексея Баранцева “Заморочки в Selenium WebDriver” с 57:11.

Чтобы хоть немножко облегчить эту заморочку, мы добавили проверку “should have href” для ссылок:

  `$("a").shouldHave(href("/foo/bar/details.html"))`

См. issue 1272 и PR 1273.

Добавили опцию хрома “–no-sandbox”

Я где-то вычитал, что она сделает тесты на хроме стабильнее. Скрестим пальцы и будем надеяться.

См. commit 3293956d

Селенид теперь явно кидает ошибку

… если не удалось создать папку для скачивания файлов.

См. issue 1265 и commit 94ece98f](https://github.com/selenide/selenide/commit/94ece98f).

Обновились на WebDriverManager 4.2.2

См. WDM Changelog.


Видеообзор

Смотрите видеообзор данного релиза.

Новости

Приходите 4-7 ноября 2020 на онлайн-конференцию Heisenbug!

Я там тоже буду выступать:

  • Воркшоп “Как начать свой проект автоматизации с нуля (с божьей помощью и Selenide)” - для начинающих
  • Доклад “Flaky tests. Метод” - для опытных


Андрей Солнцев

ru.selenide.org

26.09.20