Дождитесь загрузки страницы в Selenium - PullRequest
216 голосов
/ 03 мая 2011

Как заставить Selenium 2.0 ждать загрузки страницы?

Ответы [ 46 ]

125 голосов
/ 06 июля 2012

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

IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00));

 wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
86 голосов
/ 18 октября 2011

Использовать класс WebDriverWait

Также см. здесь

Вы можете ожидать показать какой-то элемент. что-то вроде в C #:

WebDriver _driver = new WebDriver();
WebDriverWait _wait = new WebDriverWait(_driver, new TimeSpan(0, 1, 0));

_wait.Until(d => d.FindElement(By.Id("Id_Your_UIElement"));
34 голосов
/ 29 ноября 2011

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

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

источник: неявное ожидание

32 голосов
/ 04 мая 2011

Как правило, в Selenium 2.0 веб-драйвер должен возвращать управление вызывающему коду только после того, как определит, что страница загружена.Если этого не произойдет, вы можете позвонить waitforelemement, что повторяет вызов findelement до тех пор, пока он не будет найден или не истечет время ожидания (можно установить тайм-аут).

21 голосов
/ 15 февраля 2013

Реализация Ruby:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {
    @driver.execute_script("return document.readyState;") == "complete" 
}
17 голосов
/ 02 апреля 2014

Вы можете удалить строку System.out. Он добавлен в целях отладки.

WebDriver driver_;

public void waitForPageLoad() {

    Wait<WebDriver> wait = new WebDriverWait(driver_, 30);
    wait.until(new Function<WebDriver, Boolean>() {
        public Boolean apply(WebDriver driver) {
            System.out.println("Current Window State       : "
                + String.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState")));
            return String
                .valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState"))
                .equals("complete");
        }
    });
}
12 голосов
/ 03 сентября 2014

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

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

  2. Они открыты для состояния гонки, когда вы используете элемент, который фактически присутствует на старой и новой страницах.

Вот моя попытка общего решения, которое позволяет избежать этой проблемы (в Python):

Во-первых, общая функция ожидания (используйте WebDriverWait, если хотите, я нахожу их безобразными):

def wait_for(condition_function):
    start_time = time.time()
    while time.time() < start_time + 3:
        if condition_function():
            return True
        else:
            time.sleep(0.1)
    raise Exception('Timeout waiting for {}'.format(condition_function.__name__))

Далее, решение основано на том факте, что селен записывает (внутренний) id-номер для всех элементов на странице, включая элемент <html> верхнего уровня. Когда страница обновляется или загружается, она получает новый HTML-элемент с новым идентификатором.

Итак, если вы хотите нажать на ссылку с текстом «моя ссылка», например:

old_page = browser.find_element_by_tag_name('html')

browser.find_element_by_link_text('my link').click()

def page_has_loaded():
    new_page = browser.find_element_by_tag_name('html')
    return new_page.id != old_page.id

wait_for(page_has_loaded)

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

from contextlib import contextmanager

@contextmanager
def wait_for_page_load(browser):
    old_page = browser.find_element_by_tag_name('html')

    yield

    def page_has_loaded():
        new_page = browser.find_element_by_tag_name('html')
        return new_page.id != old_page.id

    wait_for(page_has_loaded)

И затем вы можете использовать его практически для любого взаимодействия с селеном:

with wait_for_page_load(browser):
    browser.find_element_by_link_text('my link').click()

Я считаю, что это пуленепробиваемый! Как вы думаете?

Подробнее об этом можно прочитать в блоге здесь

11 голосов
/ 24 февраля 2012

Вы также можете использовать класс: ExpectedConditions для явного ожидания появления элемента на веб-странице, прежде чем вы сможете предпринять какие-либо действия.

Вы можете использовать класс ExpectedConditions, чтобы определить, видим ли элемент:

WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));

См. ExpectedConditions class Javadoc список всех условий, которые вы можете проверить.

9 голосов
/ 08 сентября 2015

Перефразированный ответ Имрана для Java 7:

    WebDriverWait wait = new WebDriverWait(driver, 30);

    wait.until(new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver wdriver) {
            return ((JavascriptExecutor) driver).executeScript(
                "return document.readyState"
            ).equals("complete");
        }
    });
9 голосов
/ 11 мая 2012

Это серьезное ограничение WebDriver.Очевидно, что ожидание элемента не подразумевает загрузку страницы, в частности, DOM может быть полностью собран (состояние готовности), при этом JS все еще выполняется, а CSS и изображения все еще загружаются.

Я считаю, что самое простое решение - этоустановить переменную JS для события onload после того, как все инициализировано, проверить и дождаться этой переменной JS в Selenium.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...