Главный Алгоритм

Главный Алгоритм

Selenide Advent Calendar
День 1
01.12.19

Всем привет!

В западном мире начался период “Адвент”, или ожидание Рождества.

Дети распаковывают свои “рождественские календари”, в которых открывают каждый день по окошечку (и находят под ним шоколадку). В Java мире, например, ведут Java Advent Calendar, в котором разные авторы каждый день публикуют по статье. Я тоже в нём участвовал пару раз (2017 и 2018).

Я тоже решил не отставать и замутить Selenide Advent Calendar. Каждый день по статье. С 1 по 25 декабря. Начну я, а вы можете присоединиться - сообщите о себе любым способом.

Сегодняшняя тема будет такая:

Самый Главный Алгоритм

Главная фишка селенида, как многие считают - это автоматические ожидания. Вам не нужно писать лишний код типа new WebDriverWait(driver, 30).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[contains(text(),'COMPOSE')]"))), чтобы дождаться наступления какого-то события. Вам не нужно тратить время и силы, чтобы вообще думать о том, а где нужны ожидания. Вам не нужно раз за разом спотыкаться о моргнувший тест и думать, куда бы ещё добавить ожидание.

В селениде всё проще: любая строчка типа $(byText("COMPOSE")).shouldBe(visible) автоматически ждёт, если надо.

А не замедлит ли это тест?

Нет.

Если элемент уже видимый, селенид сразу пойдёт дальше. Если нет - подождёт 100 мс и проверит снова. Если снова нет - подождёт ещё 100 мс и проверит ещё раз. И так до 4 секунд. А вот если по истечении 4 секунд элемент всё ещё невидим, тогда тест упадёт.

Естественно, эти 4с и 100 мс настраиваются. Вы можете задать любой таймаут под ваш проект.

Как это работает?

Вот мы и переходим к Самому Главному Алгоритму. На самом деле он очень прост.

Вот как работает, например, метод $(".btn").shouldBe(visible):

void shouldBeVisible() {
  do {
    try {
      assert webdriver.findElement().isDisplayed() == true;
      return ok;
    }
    catch (Exception e) {
      sleep(100 мс)
    }
  } while (прошло меньше N секунд);
  throw new ElementShouldBeVisible("Ожидали: то-то, на самом деле: то-то");  // тут ещё сделать скриншот.
}

В общем-то всё просто.

Этот же код в реальности выглядит чуть сложнее. А всё потому, что он “универсальный” - не только для shouldBe(visible), но и для других операций и условий.

Как известно,

дьявол кроется в деталях

В приведённом выше коде есть масса вопросов:

  1. Какие именно ошибки ловить?
    • Exception, Error, Throwable, AssertionError, WebDriverException?
  2. В случае каких ошибок надо вылететь сразу, не продолжая ожидание?
    • например, если XPath невалидный, то он и через 4 секунды будет невалидный.
  3. Результат хороший или плохой?
    • например, если элемент не найден - это может быть ок для условия $.shouldNot(exist).
  4. В какой момент делать скриншот?
  5. Можно ли всё это кастомизировать?
    • Например, при использовании Аллюра, возможно, не стоит снимать скриншот, ведь Аллюр сам снимет скриншот.
    • Или наоборот, стоит снять скриншот и как-то передать его Аллюру?
    • (сейчас и Селенид, и Аллюр делают каждый по скриншоту, так что они дублируются)
  6. Что делать, если мы дошли до последней строки, а вот в ней-то как раз прилетел зло#учий StaleElementException?

Ответы на эти вопросы менялись с течением времени. И наверное, будут ещё меняться. Но суть остаётся.

Что теперь?

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

А может, и посоветуете, как улучшить или упростить ядро скайнета наш Главный Алгоритм.


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

ru.selenide.org

01.12.19