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

Я пишу код Java Webdriver для автоматизации моего приложения. Как я могу правильно проверить, загружена ли страница или нет? Приложение также имеет некоторые вызовы Ajax.

Я объявил неявное ожидание WebDriver.

Ответ 1

Селен делает это за вас. Или, по крайней мере, он прилагает все усилия. Иногда это бывает непродолжительным, и вы должны немного помочь ему. Обычное решение Implicit Wait, которое решает большинство проблем.

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


Связанный вопрос: Selenium WebDriver: Подождите, пока сложная страница с JavaScript (JS) для загрузки, см. мой ответ там.

Более короткая версия: вы никогда не будете уверены.

"Обычная" нагрузка проста - document.readyState. Разумеется, это реализуется Селеном. Проблемная вещь - асинхронные запросы, AJAX, потому что вы никогда не можете сказать, было ли это сделано хорошо или нет. Большинство сегодняшних веб-страниц имеют сценарии, которые запускаются вечно, и все время опроса сервера.

Различные вещи, которые вы могли бы сделать, находятся по ссылке выше. Или, как и 95% других людей, используйте Implicit Wait implicity и Explicit Wait + ExpectedConditions там, где это необходимо.

например. после щелчка, какой-то элемент на странице должен стать видимым, и вам нужно подождать:

WebDriverWait wait = new WebDriverWait(driver, 10);  // you can reuse this one

WebElement elem = driver.findElement(By.id("myInvisibleElement"));
elem.click();
wait.until(ExpectedConditions.visibilityOf(elem));

Ответ 2

Вы можете установить переменную JavaScript в WepPage, которая будет установлена ​​после ее загрузки. Вы можете поместить его в любом месте, но если вы используете jQuery, $(document).onReady не плохое место для запуска. Если нет, вы можете поместить его в тег <script> в нижней части страницы.

Преимущество этого метода в отличие от проверки видимости элемента заключается в том, что вы знаете точное состояние страницы после выполнения оператора wait.

MyWebPage.html

... All my page content ...
<script> window.TestReady = true; </script></body></html>

И в вашем тесте (пример С#):

// The timespan determines how long to wait for any 'condition' to return a value
// If it is exceeded an exception is thrown.
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5.0));

// Set the 'condition' as an anonymous function returning a boolean
wait.Until<Boolean>(delegate(IWebDriver d)
{
    // Check if our global variable is initialized by running a little JS
    return (Boolean)((IJavaScriptExecutor)d).ExecuteScript("return typeof(window.TestReady) !== 'undefined' && window.TestReady === true");
});

Ответ 3

Простой фрагмент ready2use, отлично работающий для меня

static void waitForPageLoad(WebDriver wdriver) {
    WebDriverWait wait = new WebDriverWait(wdriver, 60);

    Predicate<WebDriver> pageLoaded = new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver input) {
            return ((JavascriptExecutor) input).executeScript("return document.readyState").equals("complete");
        }

    };
    wait.until(pageLoaded);
}

Ответ 4

Недавно, когда я имел дело с приложением AJAX/RIA, у меня была такая же проблема! И я использовал неявное ожидание с временем около 90 секунд. Он ждет, пока элемент не будет доступен. Итак, что мы можем сделать, чтобы убедиться, что эта страница полностью загружена,

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

Пример:

@Before

{ implicit wait statement}

@Test

{

boolean tr1=Driver.findElement(By.xpath("xx")).isEnabled/isDisplayed;

if (tr1==true && ____)//as many conditions, to make sure, the page is loaded

{

//do the necessary set of actions...
driver.findElement(By.xpath("yy")).click();

}

}

Надеюсь, это поможет! Он находится в стадии реализации, для меня тоже...

Ответ 5

Вот как я это исправит, используя фрагмент кода, чтобы дать вам базовую идею:

public class IFrame1 extends LoadableComponent<IFrame1> {

    private RemoteWebDriver driver;

    @FindBy(id = "iFrame1TextFieldTestInputControlID" ) public WebElement iFrame1TextFieldInput;
    @FindBy(id = "iFrame1TextFieldTestProcessButtonID" ) public WebElement copyButton;

    public IFrame1( RemoteWebDriver drv ) {
        super();
        this.driver = drv;
        this.driver.switchTo().defaultContent();
        waitTimer(1, 1000);
        this.driver.switchTo().frame("BodyFrame1");
        LOGGER.info("IFrame1 constructor...");
    }

    @Override
    protected void isLoaded() throws Error {        
        LOGGER.info("IFrame1.isLoaded()...");
        PageFactory.initElements( driver, this );
        try {
            assertTrue( "Page visible title is not yet available.", 
                    driver.findElementByCssSelector("body form#webDriverUnitiFrame1TestFormID h1")
                    .getText().equals("iFrame1 Test") );
        } catch ( NoSuchElementException e) {
            LOGGER.info("No such element." );
            assertTrue("No such element.", false);
        }
    }

    /**
     * Method: load
     * Overidden method from the LoadableComponent class.
     * @return  void
     * @throws  null
     */
    @Override
    protected void load() {
        LOGGER.info("IFrame1.load()...");
        Wait<WebDriver> wait = new FluentWait<WebDriver>( driver )
                .withTimeout(30, TimeUnit.SECONDS)
                .pollingEvery(5, TimeUnit.SECONDS)
                .ignoring( NoSuchElementException.class ) 
                .ignoring( StaleElementReferenceException.class ) ;
        wait.until( ExpectedConditions.presenceOfElementLocated( 
                By.cssSelector("body form#webDriverUnitiFrame1TestFormID h1") ) );
    }
....

Ответ 6

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

Ответ 7

Я знаю, что этот пост старый. Но после сбора всего кода сверху я сделал хороший метод (решение) для работы с ajax и регулярными страницами. Код создан только для С# (так как Selenium определенно лучше подходит для С# Visual Studio после года беспорядка).

Метод используется как метод расширения, что означает, что это простой способ; что вы можете добавить больше функциональности (методов) в этом случае к объекту IWebDriver. Важно то, что вам нужно определить: 'this' в параметрах, чтобы использовать его.

Переменная тайм-аута - это количество секунд, в течение которых веб-сервер ожидает, если страница не отвечает. Используя пространства имен Selenium и Selenium.Support.UI, можно выполнить часть javascript, которая возвращает логическое значение, независимо от того, готов ли документ (завершен) и загружен ли jQuery. Если на странице нет jQuery, тогда метод выдает исключение. Это исключение "уловлено" обработкой ошибок. В состоянии catch документ будет проверяться только на состояние готовности, не проверяя jQuery.

public static void WaitUntilDocumentIsReady(this IWebDriver driver, int timeoutInSeconds) {
    var javaScriptExecutor = driver as IJavaScriptExecutor;
    var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));

    try {
        Func<IWebDriver, bool> readyCondition = webDriver => (bool)javaScriptExecutor.ExecuteScript("return (document.readyState == 'complete' && jQuery.active == 0)");
        wait.Until(readyCondition);
    } catch(InvalidOperationException) {
        wait.Until(wd => javaScriptExecutor.ExecuteScript("return document.readyState").ToString() == "complete");
    }
}

Ответ 8

Ниже приведен код из моего класса BasePageObject для ожиданий:

public void waitForPageLoadAndTitleContains(int timeout, String pageTitle) {
    WebDriverWait wait = new WebDriverWait(driver, timeout, 1000);
    wait.until(ExpectedConditions.titleContains(pageTitle));
}

public void waitForElementPresence(By locator, int seconds) {
    WebDriverWait wait = new WebDriverWait(driver, seconds);
    wait.until(ExpectedConditions.presenceOfElementLocated(locator));
}

public void jsWaitForPageToLoad(int timeOutInSeconds) {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    String jsCommand = "return document.readyState";

    // Validate readyState before doing any waits
    if (js.executeScript(jsCommand).toString().equals("complete")) {
        return;
    }

    for (int i = 0; i < timeOutInSeconds; i++) {
        TimeManager.waitInSeconds(3);
        if (js.executeScript(jsCommand).toString().equals("complete")) {
            break;
        }
    }
}

   /**
     * Looks for a visible OR invisible element via the provided locator for up
     * to maxWaitTime. Returns as soon as the element is found.
     *
     * @param byLocator
     * @param maxWaitTime - In seconds
     * @return
     *
     */
    public WebElement findElementThatIsPresent(final By byLocator, int maxWaitTime) {
        if (driver == null) {
            nullDriverNullPointerExeption();
        }
        FluentWait<WebDriver> wait = new FluentWait<>(driver).withTimeout(maxWaitTime, java.util.concurrent.TimeUnit.SECONDS)
                .pollingEvery(200, java.util.concurrent.TimeUnit.MILLISECONDS);

        try {
            return wait.until((WebDriver webDriver) -> {
                List<WebElement> elems = driver.findElements(byLocator);
                if (elems.size() > 0) {
                    return elems.get(0);
                } else {
                    return null;
                }
            });
        } catch (Exception e) {
            return null;
        }
    }

Поддерживающие методы:

     /**
     * Gets locator.
     *
     * @param fieldName
     * @return
     */
    public By getBy(String fieldName) {
        try {
            return new Annotations(this.getClass().getDeclaredField(fieldName)).buildBy();
        } catch (NoSuchFieldException e) {
            return null;
        }
    }