Ожидания в стиле Java 8

083402_kx1b2e8athumbnail

На мысль навел просмотр видео, в котором Сергей Король справедливо напомнил, что многие из нас «упираются» собственно в средства Селениума и не используют всю силу благословенной Java. Уже вышла 9 версия, а многие еще недостаточно освоили 8, часто ли вы используете в проекте лямбды, стримы, функциональные интерфейсы?

Покажу небольшой пример применения функциональных интерфейсов для ожиданий, который делает код кратким, понятным и, главное, вполне в стиле 8 Java. Идею я честно взял из вышеуказанного видео, немного поправив для своих нужд.

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

import org.openqa.selenium.By;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;

import java.util.function.Function;

public enum WaitConditions {
   visible   (ExpectedConditions::visibilityOfElementLocated),
   exist     (ExpectedConditions::presenceOfAllElementsLocatedBy),
   clickable (ExpectedConditions::elementToBeClickable),
   invisible (ExpectedConditions::invisibilityOfElementLocated);

   WaitConditions(Function<By, ExpectedCondition> type) {
      this.type = type;
   }

   public Function<By, ExpectedCondition> getType() {
      return type;
   }

   private final Function<By, ExpectedCondition> type;
}

Тип нашего enum  это функциональный интерфейс Function, который получает на вход By (наш локатор) и возвращает ExpectedCondition то есть те самые условия ожидания.

 visible (ExpectedConditions::visibilityOfElementLocated),
 exist (ExpectedConditions::presenceOfAllElementsLocatedBy),
 clickable (ExpectedConditions::elementToBeClickable),
 invisible (ExpectedConditions::invisibilityOfElementLocated);

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

private final Function<By, ExpectedCondition> type;

Обратите внимание на ? — это необходимо для использования invisibilityOfElementLocated, так как он в отличие от остальных методов возвращает ExpectedCondition.

С enum разобрались, теперь посмотрим на метод, который будет использовать его. Сразу оговорюсь,  я использую возвращаемое значение boolean, а не кидаю исключение выше, но это мой стиль работы, вы можете модифицировать метод:

public boolean waitFor(By locator, WaitConditions conditions) {
   WebDriverWait wait = new WebDriverWait(driver, defaulTime);
   try {
      wait.until(conditions.getType().apply(locator));
      return true;
   } catch (TimeoutException ex) {
      //делаем скриншот, логируем и  т.д.
      return false;
   }
}

defaultTime — это переменная int, сколько конкретно секунд ждать по умолчанию, при желании ее можно менять, driver это конечно же наш WebDriver. Вот тут все происходит wait.until(conditions.getType().apply(locator)); — наш локатор используется для ожидания соответствующего типа.

Не так много кода мы написали, но все это просто и лаконично позволит нам в коде писать вызовы наших ожиданий в стиле

waitFor(By.id("loginButton"), visible);
или
waitFor(submitButton, clickable);

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

Software-Testing.Ru

Реклама