Временно обходя скрытые ожидания с помощью WebDriver
При использовании неявных ожиданий как указано здесь, я по-прежнему иногда хочу утверждать невидимую немедленную или несуществование элементов.
Другими словами, я знаю, что некоторые элементы должны быть скрыты и хотят, чтобы мои тесты быстро выполняли это утверждение, не затрачивая несколько секунд из-за (в противном случае полезного) неявного ожидания.
Одна вещь, которую я пробовал, была вспомогательным методом, подобным этому:
// NB: doesn't seem to do what I want
private boolean isElementHiddenNow(String id) {
WebDriverWait zeroWait = new WebDriverWait(driver, 0);
ExpectedCondition<Boolean> c = invisibilityOfElementLocated(By.id(id));
try {
zeroWait.until(c);
return true;
} catch (TimeoutException e) {
return false;
}
}
Но в приведенном выше коде вызов until()
возвращает только после того, как неявное время ожидания прошло, т.е. оно не делает то, что я хотел.
Это единственный способ, который я нашел до сих пор:
@Test
public void checkThatSomethingIsNotVisible() {
turnOffImplicitWaits();
// ... the actual test
turnOnImplicitWaits();
}
... где, например, turnOffImplicitWaits()
является вспомогательным в общем суперэлементе селена:
protected void turnOffImplicitWaits() {
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
}
Но это не очень элегантно, я думаю. Есть ли какой-нибудь более чистый способ обхода неявного ожидания иногда?
Ответы
Ответ 1
Учитывая, что Selenium, кажется, не предлагает то, что я хочу напрямую (на основе того, что сказал Майк Кван и Slanec), этот простой вспомогательный метод - это то, к чему я пошел сейчас:
protected boolean isElementHiddenNow(String id) {
turnOffImplicitWaits();
boolean result = ExpectedConditions.invisibilityOfElementLocated(By.id(id)).apply(driver);
turnOnImplicitWaits();
return result;
}
private void turnOffImplicitWaits() {
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
}
private void turnOnImplicitWaits() {
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
Если элемент скрыт или вообще отсутствует, метод возвращает true; если он виден, возвращает false. В любом случае, проверка выполняется мгновенно.
Использование вышеописанного, по крайней мере, намного более чистое, чем забивание самих тестовых случаев вызовами turnOffImplicitWaits()
и turnOnImplicitWaits()
.
См. также эти ответы для уточненных версий того же подхода:
Ответ 2
Я также предлагаю изменить параметр на локатор "By" для большей гибкости при поиске элемента.
protected boolean isElementHiddenNow(By locator) {
turnOffImplicitWaits();
boolean result = false;
try {
result = ExpectedConditions.invisibilityOfElementLocated(locator).apply(driver);
}
finally {
turnOnImplicitWaits();
}
return result;
}
Таким образом, вы можете искать css при необходимости, а не просто id:
By PartLinkLocator = By.cssSelector("div.search-result div.row a");
'Конечно, ваш локатор, вероятно, должен быть сконструирован так, чтобы возвращать только один элемент (в отличие от примера "By", который я быстро схватил, который возвращает все ссылки частей в таблице css строк...) Итак, пример "id" будет выглядеть как
By usernameLocator = By.id("inputEmail");
myResult = isElementHiddenNow(usernameLocator);
Ответ 3
Моя реализация:
using (driver.NoImplicitWait())
{
....
}
С помощью метода расширения:
public static NoImplicitWait NoImplicitWait(this IWebDriver driver)
{
return new NoImplicitWait(driver);
}
И класс:
public sealed class NoImplicitWait : IDisposable
{
private readonly IWebDriver _driver;
public NoImplicitWait(IWebDriver driver)
{
_driver = driver;
_driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0));
}
public void Dispose()
{
_driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(30));
}
}
Ответ 4
@Jonic ответ мне помог, однако я добавил бы try { } finally { }
и вызывал turnOnImplicitWaits()
в блок finally
, чтобы убедиться, что он всегда возвращается.
protected boolean isElementHiddenNow(String id) {
turnOffImplicitWaits();
boolean result = false;
try {
result = ExpectedConditions.invisibilityOfElementLocated(By.id(id)).apply(driver);
}
finally {
turnOnImplicitWaits();
}
return result;
}
Ответ 5
Мой подход состоял в том, чтобы полностью обходить Неявное ожидание и переопределить его (с добавлением проверки видимости и т.д.) в моих собственных методах findElement()
и findElements()
, которые я теперь использую по умолчанию. Таким образом, когда я хочу проверить что-то мгновенно, я могу вызвать оригинальный метод WebDriver, который, конечно же, не ждет.
Ответ 6
В существующем коде, который много полагается на неявный подход к выживанию, и без CSS для спасения, я нашел выход для такого рода вещей, дополняя его Jsoup и продолжая работу с Jsoup:
# this is straightforward Scala... put the types and it is Java.
val innerHtml = seleniumWebElementFatherInstance.getAttribute("innerHTML")
val jsoupElements = Jsoup.parse(innerHtml).select("div.your.css.selector")