Должен ли 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);
}