Должен ли Selenium findElements() неявно ждать возврата 0 элементов?

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

Assert.assertEquals(page.getSearchResultList().size(), 0);

Просто так и работает но... медленно из-за implicitlyWait.

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

Из-за того, что когда я удаляю элемент, то getSearchResultList().size() равно 0, и Selenium всегда ждет 10 секунд, прежде чем findElements() вернет 0 size.

Чтобы избежать этого 10-секундного ожидания, у меня есть обходной путь для изменения неявно Wait непосредственно перед моим утверждением, но я думаю, что это не очень хорошая идея.

page.getDriver().manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
Assert.assertEquals(page.getSearchResultList().size(), 0);

Есть ли другое, лучшее решение?

Обновление по запросу @KunduK

Утверждение без WebDriverWait:

    Instant start = Instant.now();
    List<WebElement> resultSearchList = page.getDriver().findElements(By.cssSelector("[ng-repeat='searchResult in $ctrl.searchResults']"));
    Assert.assertEquals(resultSearchList.size(), 0);
    Instant stop = Instant.now();
    log.debug("Assert Took: " + Duration.between(start, stop).getSeconds() + " sec");

Выход:

10:49:59.081 [main] DEBUG impl.AssertNewEntityPage - Assert Took: 10 sec

Утверждение с помощью WebDriverWait

    Instant start = Instant.now();
    new WebDriverWait(page.getDriver(), 10).until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("[ng-repeat='searchResult in $ctrl.searchResults']")));
    List<WebElement> resultSearchList = page.getDriver().findElements(By.cssSelector("[ng-repeat='searchResult in $ctrl.searchResults']"));
    Assert.assertEquals(resultSearchList.size(), 0);
    Instant stop = Instant.now();
    log.debug("Assert Took: " + Duration.between(start, stop).getSeconds() + " sec");

Выход:

10:57:08.215 [main] DEBUG impl.AssertNewEntityPage - Assert Took: 20 sec

3 ответа

Решение

stalenessOf()

stalenessOf() это ожидание ожидания, пока элемент больше не будет прикреплен к DOM.


Этот вариант использования

Это UseCase из ... удаление элемента в веб - приложение... Карты для ExpectedConditions изstalenessOf(WebElement element). Таким образом, ваш блок кода будет таким:

new WebDriverWait(driver, 10).until(ExpectedConditions.stalenessOf(By.cssSelector("cssSelector_of_element_to_be_stale")));
Assert.assertEquals(page.getSearchResultList().size(), 0);

Примечание. Поскольку ваш вариант использования уже включает implicitlyWait, и в этом ответе предлагается вызвать WebDriverWait, т.е. ExplicitWait, в соответствии с документацией ... Не смешивайте неявное и явное ожидание. Это может привести к непредсказуемому времени ожидания. Например, установка неявного ожидания в 10 секунд и явного ожидания в 15 секунд может вызвать тайм-аут через 20 секунд...

Вы можете найти соответствующее обсуждение в Как объединить неявные и явные тайм-ауты в Selenium?

Вы можете использовать ExpectedConditions.invisibilityOfElementLocated() чтобы дождаться невидимого элемента, а затем взять size() элементов.

new WebDriverWait(driver, 10).until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("locator xpath")));
List<WebElement> elements = driver.findElements(By.xpath("locator xpath"));
Assert.assertEquals(elements.size(), 0);

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

public static boolean waitForJSandJQueryToLoad() {
    log.info("Waiting for jQuery to load...");
    ExpectedCondition<Boolean> jQueryLoad = d -> {
        try {
            log.info("jQuery presented.");
            return ((Long) ((JavascriptExecutor) driver).executeScript("return jQuery.active") == 0);
        } catch (Exception e) {
            log.info("No jQuery presented.");
            return true;
        }
    };
    log.info("Waiting for javascript to load...");
    ExpectedCondition<Boolean> jsLoad = d -> ((JavascriptExecutor) driver).executeScript("return document.readyState")
            .toString().equals("complete");
    return wait.until(jQueryLoad) && wait.until(jsLoad);
}    
Другие вопросы по тегам