Проблема использования неявного ожидания и явного ожидания сводится к fl aws в том, как ExpectedConditions
реализовано в исходном коде Selenium.
Позвольте мне объяснить проблему, проанализировав следующий код:
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
WebElement element = new WebDriverWait(driver, 5, 1000).until(ExpectedConditions.elementToBeClickable(By.id("some_id")));
- Мы инициализируем драйвер и устанавливаем неявное ожидание на 10 секунд. Это означает, что
driver.findElement()
будет ждать 10 секунд, пока элемент не будет найден, прежде чем выбросить NoSuchElementException
. Это очень важный момент для заметки . - Затем мы устанавливаем явное ожидание с продолжительностью 5 секунд и временем ожидания между опросом 1000 миллисекунд (1 секунда). Это означает, что
WebDriverWait
будет опрашивать ExpectedConditions
, чтобы быть правдой каждую 1 секунду до 5 секунд. Если ExpectedConditions
вернет true, опрос остановится и объект, указанный в ExpectedConditions
, будет возвращен. В приведенном выше примере кода возвращаемым объектом является WebElement
. В случае, если ExpectedConditions
ложно через 5 секунд, выдается TimeoutException
( ИЛИ ТАК МЫ ЖДЕМ ). Теперь пришло время посмотреть, что происходит в ExpectedConditions
. Код ExpectedConditions.elementToBeClickable()
имеет следующий синтаксис.
public static ExpectedCondition<WebElement> elementToBeClickable(final By locator) {
return new ExpectedCondition<WebElement>() {
@Override
public WebElement apply(WebDriver driver) {
WebElement element = visibilityOfElementLocated(locator).apply(driver);
try {
if (element != null && element.isEnabled()) {
return element;
}
return null;
} catch (StaleElementReferenceException e) {
return null;
}
}
};
}
В свою очередь elementToBeClickable
выше, в свою очередь, вызывает visibilityOfElementLocated()
метод для подтверждения, если элемент виден.
public static ExpectedCondition<WebElement> visibilityOfElementLocated(final By locator) {
return new ExpectedCondition<WebElement>() {
@Override
public WebElement apply(WebDriver driver) {
try {
return elementIfVisible(driver.findElement(locator));
} catch (StaleElementReferenceException e) {
return null;
}
}
};
}
5.Примечание как driver.findElement(locator)
Вызывается выше в методе visibilityOfElementLocated()
. В случае, если элемент не найден, будет применено неявное ожидание в 10 секунд. Поэтому водитель будет ждать 10 секунд, пока не выдаст NoSuchElementException
.
Но подождите (каламбур не преднамеренный)! не установлено ли для нашего явного ожидания время ожидания в 5 секунд при условии elementToBeClickable()
? Да, это так, но неявное ожидание будет применено первым. WebDriverWait перехватит NoSuchElementException
и выдаст TimeoutException
через 10 секунд вместо установленного явного ожидания в 5 секунд. В этом и заключается проблема, которую пытается решить решение вопроса. Решение пытается установить неявное ожидание на 0 секунд, чтобы условие явного ожидания выполнялось правильно, а затем сбрасывает неявное ожидание.
Реализация, представленная в Вопросе, выполняет работу без одной детали. Неявное ожидание жестко запрограммировано на 3 секунды, что не идеально. То, как вы предоставляете неявное ожидание как глобальную универсальную константу, очень специфично c. Мы устанавливаем неявное ожидание на драйвере, и мы можем ожидать неявное ожидание, как «драйвер» driver.manage().timeouts().getImplicitWait()
. Хотя это и идеально, к сожалению, это НЕ возможно напрямую. Есть обходные пути, у @forresthopkinsa есть довольно интересное решение по созданию расширенных драйверов для получения неявных ожиданий
ОБНОВЛЕНИЕ (24 марта 2020 г.)
В: Этот подход мне подходит, но я не уверен в этом. Может ли смешивание неявных и явных ожиданий, подобных этому, вызывать какие-либо проблемы?
Я спрашиваю, что если неявное ожидание каждый раз устанавливается в ноль перед выполнением явного ожидания, тогда это нормально? Это все еще вызовет проблемы непредсказуемых ожиданий? Это вызовет другие проблемы?
Насколько я понимаю, не должно быть никаких проблем с установкой неявного ожидания на 0, а затем с выполнением явного ожидания и последующим переключением обратно, поскольку нет никаких ограничений на установку неявного ожидание в любой момент времени во время выполнения теста.
Кроме того, если вы думаете об этом, вы действительно не смешиваете неявное ожидание и явное ожидание в решении с точки зрения выполнения кода. На самом деле вы делаете противоположное! Если вы установили неявное ожидание для определенного ненулевого значения, а затем выполнили явное ожидание, то здесь происходит реальное микширование. Сначала выполняется неявное, если применимо, а затем выполняется явное ожидание, приводящее к несоответствиям. Если вы установите неявное ожидание равным 0, вы уберете неявное ожидание из уравнения времени ожидания!
Проблема непредсказуемых ожиданий не возникнет с решением в OP.