Selenium ждать пока загрузится страница java

Селен ждет: неявный, явный, беглый и сон

Selenium ждет загрузки страницы, которая играет важную роль в ваших сценариях Selenium. Они помогают сделать их менее рыхлыми и более надежными. Selenium обеспечивает многократное ожидание, чтобы обеспечить адекватное ожидание или паузу в выполнении сценария в зависимости от определенных условий. Таким образом, вы гарантируете, что не получите неудачные сценарии при выполнении автоматизации тестирования с Selenium . В этом уроке мы будем объяснять типы ожидания и сна Selenium, примеры в реальном времени и сравнительное исследование. Давайте начнем с ответа на ключевой вопрос: «Почему мы должны использовать Selenium Waits?»

Зачем нам нужен Selenium Waits?

Большинство современных приложений построено на JavaScript или Ajax с использованием таких платформ, как React, Angular или любых других, для загрузки веб-элементов которых требуется определенное время при загрузке или обновлении этой страницы. Следовательно, в случае, если вы захотите найти в своем скрипте элемент, который еще не загружен на страницу, selenium выдаст вам сообщение « ElementNotVisibleException ».

Приведенный ниже фрагмент кода поможет вам продемонстрировать ту же проблему, что и при выполнении автоматического тестирования с Selenium. В этом фрагменте кода я использую пример easemytrip.com, где пользователь почты выбирает пункт назначения «От» и «До» с датой поездки, веб-приложение загружает необходимые данные о рейсе в течение определенного времени. В этом случае, не применяя ожидание, пользователь стремится забронировать первый рейс из списка. Теперь, поскольку страница еще не загружена, сценарию не удалось найти кнопку «Забронировать сейчас». В результате возникает исключение NoSuchElementException . Фрагмент кода и вывод консоли ниже:

Читайте также:  Php curl get url contents

Источник

. что делать в Selenium, если страница загружается слишком долго?

. что делать в Selenium, если страница загружается слишком долго?

В предыдущей статье я рассказал, как Selenium ожидает завершения загрузки страницы.

Вкратце повторю: перед выполнением каждой команды он проверяет значение свойства document.readyState и приостанавливает выполнение команды до тех пор, пока это свойство не приобретёт значение complete .

Однако иногда эта стратегия приводит к провалу. Бывают такие ситуации, когда свойство document.readyState либо очень долго не может попасть в состояние complete, либо вообще никогда не достигает этого состояния.

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

Вот реальный пример, который демонстрирует эту проблему:

// инициализируем драйвер WebDriver driver = new FirefoxDriver(); WebDriverWait wait = new WebDriverWait(driver, 10); // открываем сайт, ждём загрузки страницы driver.get("http://www.sazehgostar.com/SitePages/HomePage.aspx"); // кликаем кнопку driver.findElement(By.id("en")).click(); // ждём загрузки следующей страницы wait.until(visibilityOfElementLocated(By.id("menu")));

На моей машине выполнение этого фрагмента кода занимает от 20 до 40 секунд (без учёта времени на запуск браузера). Причина как раз в том, что на страницу грузится большая картинка (~7 мегабайт). При этом нужная кнопка для переключения на английскую версию сайта становится доступна уже через несколько секунд, но Selenium ждёт, пока загрузится вся страница целиком.

Можно ли что-нибудь сделать, чтобы Selenium не ждал так долго?

Таймаут ожидания загрузки

Установка таймаута ожидания загрузки приводит к тому, что операция get выбрасывает исключение TimeoutException , если страница не успела загрузиться в течение заданного количества времени. При этом после возникновения исключения загрузка страницы не прерывается, но зато появляется возможность “досрочно” выполнять с ней какие-нибудь действия. Однако следует помнить, что на такой “недозагруженной” странице нужные для дальнейших действий элементы ещё могли не появиться, поэтому требуются дополнительные ожидания появления элементов:

// инициализируем драйвер WebDriver driver = new FirefoxDriver(); WebDriverWait wait = new WebDriverWait(driver, 10); // устанавливаем таймаут ожидания загрузки driver.manage().timeouts().pageLoadTimeout(1, TimeUnit.SECONDS); // открываем сайт, но ждём недолго try  driver.get("http://www.sazehgostar.com/SitePages/HomePage.aspx"); > catch (TimeoutException ignore)  > // ждём появления кнопки на "недозагруженной" странице WebElement button = wait.until(visibilityOfElementLocated(By.id("en"))); // кликаем try  button.click(); > catch (TimeoutException ignore)  > // ждём загрузки следующей страницы wait.until(visibilityOfElementLocated(By.id("menu")));

В таком варианте код выполняется примерно за 4 секунды (без учёта времени на запуск браузера).

Быстро – ещё не значит правильно 🙂

Дело в том, что элемент с идентификатором menu есть как на первой странице, так и на второй. В тот момент, когда выполняется клик по кнопке с идентификатором en (переключение на английскую версию сайта), элемент с идентификатором menu тоже присутствует на странице. И Selenium, вместо того, чтобы после клика ждать загрузки второй страницы, немедленно “находит” этот элемент на первой странице.

Причина этого в том, что, как я уже упоминал, после возникновения TimeoutException загрузка страницы не прерывается, она продолжает загружаться, в том числе и в момент выполнения команды click . Это сбивает Selenium с толку, он не понимает, что должна появиться другая страница, и вместо этого ищет элементы на текущей странице.

Ну, раз уж мы отобрали у Selenium и взяли на себя ответственность за ожидание загрузки страницы, надо брать ответственность и за “выгрузку” страницы тоже. То есть перед ожиданием появления элемента, который должен найтись на следующей странице, нужно сначала подождать, пока исчезнет элемент, находящийся на текущей странице. Например, исчезнет та самая кнопка, по которой кликали:

// инициализируем драйвер WebDriver driver = new FirefoxDriver(); WebDriverWait wait = new WebDriverWait(driver, 10); // устанавливаем таймаут ожидания загрузки driver.manage().timeouts().pageLoadTimeout(1, TimeUnit.SECONDS); // открываем сайт, но ждём недолго try  driver.get("http://www.sazehgostar.com/SitePages/HomePage.aspx"); > catch (TimeoutException ignore)  > // ждём появления кнопки на "недозагруженной" странице WebElement button = wait.until(visibilityOfElementLocated(By.id("en"))); // кликаем try  button.click(); > catch (TimeoutException ignore)  > // ждём исчезновения кнопки, то есть "выгрузки" страницы wait.until(stalenessOf(button)); // ждём загрузки следующей страницы wait.until(visibilityOfElementLocated(By.id("menu")));

Теперь этот фрагмент кода выполняется примерно 10 секунд (без учёта времени на запуск браузера), и это правильно – около 5 секунд на каждую страницу.

Недостаток описанного выше способа заключается в том, что приходится оборачивать в блок try-catch все вызовы команд, которые могут привести к началу загрузки новой страницы. А это может быть вообще говоря любая команда. То есть исключение TimeoutException нужно ожидать буквально везде. Это ужасно!

К счастью, есть другой способ.

Стратегия ожидания загрузки

Если вы ещё помните, Selenium перед выполнением каждой команды он проверяет значение свойства document.readyState и приостанавливает выполнение команды до тех пор, пока это свойство не приобретёт значение complete .

В процессе обработки страницы браузер меняет это свойство, отражая информацию о текущем этапе загрузки:

  • loading означает, что страница ещё загружается,
  • interactive означает, что основное содержимое страницы загрузилось и отрисовалось, пользователь уже может с ней взаимодействовать, но ещё продолжается загрузка дополнительных ресурсов,
  • complete означает, что все дополнительные ресурсы тоже загружены.

Так вот, можно изменить настройки Selenium так, чтобы он ждал не значения complete , а значения interactive , или даже вообще не ждал ничего.

Для этого при инициализации драйвера надо установить подходящее значение для capability с названием pageLoadStrategy .

  • normal (установлено по умолчанию) – ждать, пока свойство document.readyState примет значение complete
  • eager – ждать, пока свойство document.readyState примет значение interactive
  • none – вообще не ждать

Конечно, и в этом случае тоже приходится брать на себя ответственность за ожидание “выгрузки” страниц.

Вот тот же самый пример, на этот раз без таймаутов, но с изменённой стратегией ожидания:

// инициализируем драйвер DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(CapabilityType.PAGE_LOAD_STRATEGY, "eager"); WebDriver driver = new FirefoxDriver(capabilities); WebDriverWait wait = new WebDriverWait(driver, 10); // открываем сайт driver.get("http://www.sazehgostar.com/SitePages/HomePage.aspx"); // ждём появления кнопки на "недозагруженной" странице WebElement button = wait.until(visibilityOfElementLocated(By.id("en"))); // кликаем button.click(); // ждём исчезновения кнопки, то есть "выгрузки" страницы wait.until(stalenessOf(button)); // ждём загрузки следующей страницы wait.until(visibilityOfElementLocated(By.id("menu")));

В этом варианте сценарий тоже отрабатывает примерно за 10 секунд (без учёта времени на запуск браузера).

P.S. Я думаю, вы поняли, что с использованием только неявных (implicit) ожиданий описанные выше трюки сделать не получится.

Алексей Баранцев

Автор: Алексей Баранцев

Если вам понравилась эта статья, вы можете поделиться ею в социальных сетях (кнопочки ниже), а потом вернуться на главную страницу блога и почитать другие мои статьи.
Ну а если вы не согласны с чем-то или хотите что-нибудь дополнить – оставьте комментарий ниже, может быть это послужит поводом для написания новой интересной статьи.

Источник

Оцените статью