Явные и неявные ожидания - помогите разобраться

Скорее правильнее будет в методах, где ты используешь явные ожидания добавить условие что если приходящий таймаут ну к примеру меньше 2-х секунд то ты делаешь Implicity wait в 500 миллисекунд, а после выполнения возвращаешь в дефолтные ну к примеру 5, 20… А пейджам такие тонкости вообще знать не нужно.

1 лайк
Кажется начинаю понимать - то есть, если я отключил неявные ожидания, то на каждой странице нужно реализовать какой-то метод

ты их не отключаешь .Если стоит ты говоришь проверить DOM если этот єлемент прям сейчас .
если ставишь время он ждет периодичски проверяя не появился ли.

1 лайк

Ребята, что-то совсем запутался - так стоит ли вообще устанавливать в 0/оставлять по умолчанию неявные ожидания?

Скорее правильнее будет в методах, где ты используешь явные ожидания добавить условие что если приходящий таймаут ну к примеру меньше 2-х секунд то ты делаешь Implicity wait в 500 миллисекунд, а после выполнения возвращаешь в дефолтные ну к примеру 5, 20… А пейджам такие тонкости вообще знать не нужно.

Не очень понял, можно поподробнее и с примером?
Я планировал установить неявные нулю и пользоваться только явными, а тут получается комбинированный способ. К тому же прочитал тут Руководство пользователя

По умолчанию значение равно 0. Будучи однажды установлено, значение неявного ожидания останется действительным на протяжении всего существования экземпляра объекта “WebDriver”.

Тогда каким образом менять установленные 500 мс на дефолтные? :confused:

Вот такой вот пример. Специально написал все в одном методе, но лучше разделить на 2.
Проверь как работает без изменения implicityWait и как с ним… на примерах глобального implicityWait в 10 секунд и таймаута в метод допустим 2 секунды, при условии что элемент невидим.
Где берется драйвер тоже не важно :smile:

public static boolean isElementVisible(WebElement webElement, int timeOut) {
	boolean isElementVisible = false;
	WebDriverWait wait = new WebDriverWait(driver, timeOut);
	if (timeOut < DEFAULT_TIMEOUT || timeOut < 2){
		driver.manage().timeouts().implicitlyWait(500, TimeUnit.MILLISECONDS);
	}		  
	try {
		wait.until(ExpectedConditions.visibilityOf(webElement));
		isElementVisible =  true;
	} finally {
		driver.manage().timeouts()
                      .implicitlyWait(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
	}
	return isElementVisible;
}

Да кстати если поставишь в ноль implicityWait то получишь ситуацию когда элементы через driver.findElement() и аннотация будут искаться вообще без задержек и будешь получать очень много падений с NoSuchElementException

Все-таки так и остался вопросы:

1. Нужно ставить на 0 неявные ожидания для использования WebDriverWait?

2. Если неявные ожидания = 0, а при инициализации страниц делается

 PageFactory.initElements(new AjaxElementLocatorFactory(driver, 30), this);

То при обращении к элементу страницы будет использовано ожидание 30, а не 0? Так ведь?

1 лайк

Ооо, большое спасибо за ответ и отдельное спасибо за ссылку на обсуждение!

Вот что полезного для себя узнал:

  1. Время неявного ожидания по дефолту = 0, так что можно это не указывать (но я наверное укажу для наглядности),
  2. При обращении к элементу через страницу на самом деле выполняется driver.findElement,
  3. Соответственно если время неявных ожиданий = 0, то ждать появления при findElement не будет,
  4. Но если при инициализации страниц использовать AjaxElementLocatorFactory, то при обращении к элементу через страницу каждые 250 мс на протяжении N секунд указанных в конструкторе будет проверяться наличие элемента (командой findElement). В свою очередь findElement ждет N секунд, установленных в implicitlyWait. А если установлено 0, то и ждать не будет.

Прошу поправьте меня, если я где-то неправильно написал :relieved:


Теперь осталось уяснить на счет зависимости WebDriverWait и времени в implicitlyWait. Работает ли это так же (по аналогии) как и AjaxElementLocatorFactory? Т.е. если допустим implicitlyWait = 10 секунд, то при ожидании через WebDriverWait будет что-то подобное:

  1. Один раз в 500 мс WebDriverWait вызывает findElement,

  2. findElement в свою очередь 10 секунд ждет появления элемента, а
    затем, если его не нашел, отваливается с NoSuchElementException,

  3. Но так как в WebDriverWait игнорируется такое исключение, после
    этого, через 500 мс он снова ищет элемент, используя findElement

Так ли это? :blush:

Так. Причем если в WebDriverWait сетнуть таймаут 2 секунды, по факту будет ждать 10 секунд и будет только один запрос к драйверу на findElement.

1 лайк

Да и по большому счету тебе без разницы сколько тех миллисекунд будет в implicityWait все равно в методы с ожиданиями обычно передаются секунды (а то свихнуться можно), главное чтобы implicityWait при поиске через явные ожидания был меньше чем WebDriverWait, а при поиске обычными ожиданиями его хватало чтобы точно найти элементы.

А зачем мне тогда искать неявными ожиданиями? Я лучше установлю их в 0 и при поиске буду искать с явным ожиданием, через webdriverwait. Поиск элементов на странице будет искаться через AjaxElementLocatorFactory, что по сути тот же webdriverwait.

Или могут быть какие-то случаи когда мне понадобится искать обязательно неявными ожиданиями?

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

1 лайк

Просто не трогать их, по умолчанию они отключены

Ответ на вопросы 2, 3, 4:
Если при инициализации элементов используется AjaxElementLocator, то при обращении к полям класса страницы WebDriver будет ожидать появления в DOM данного элемента в течение указанного при инициализации времени (в твоем примере 10 сек). Если находит раньше, сразу обращается к нему. Поиск происходит в момент обращения к полю класса страницы

2 лайка
Тогда каким образом менять установленные 500 мс на дефолтные? confused
Ответить в новой связанной теме

Можно . Есть еще такое ожидание Fluent

Waiting 30 seconds for an element to be present on the page, checking

   // for its presence once every 5 seconds.
   Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
       .withTimeout(30, SECONDS)
       .pollingEvery(5, SECONDS)
       .ignoring(NoSuchElementException.class);

   WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
     public WebElement apply(WebDriver driver) {
       return driver.findElement(By.id("foo"));
     }
   });

но зачем ? :grinning:

1 лайк

Всем большое спасибо за помощь! Всё стало намного понятнее. Надеюсь эта тема будет полезна не только мне, но и другим людям, столкнувшимся с вопросом по явным и неявным ожиданиям :blush:

Чуть не забыл
если используешь эту ботву

new AjaxElementLocatorFactory(webDriver, 10)

старайся не использовать Xpath .

Серьезно? А почему?

1 лайк

Присоединяюсь к вопросу?
Только надеюсь будете оперировать фактами, а не выдержками из javadoc который написан много лет назад неизвестно кем :slight_smile:

Где то в исходниках по этому классу натыкался на

а не выдержками из javadoc который написан много лет назад неизвестно кем 

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

Есть много причин:

  1. Жизнь локатра Xpath очень короткая, так как многие изменения на странице сделают этот локатор невалидным
  2. Поиск по Xpath в ИЕ очень медленный. В хроме вы можете не заметить визуально этого, но ИЕ это видно сразу же.
  3. Писать правильные умные Xpath, которые не будут ломаться при изменениях, не так легко как кажется - CSS локаторы в разы проще

Я имел ввиду конкретно для реализации PageFactory.initElements(new AjaxElementLocatorFactory(webDriver, 10), page);