使用WebDriver暂时绕过隐式等待

当使用隐式等待时, 正如这里所建议的那样 ,我仍然有时想要断言元素的直接不可见性或不存在。

换句话说,我知道应该隐藏一些元素,并且希望我的测试能够快速地进行断言,而不需要花费几秒钟因为(否则有用)隐式等待。

我试过的一件事就是像这样的辅助方法:

// NB: doesn't seem to do what I want private boolean isElementHiddenNow(String id) { WebDriverWait zeroWait = new WebDriverWait(driver, 0); ExpectedCondition 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()是常见Selenium超类中的助手:

 protected void turnOffImplicitWaits() { driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); } 

但我觉得这不是很优雅。 是否有任何更清洁的方法偶尔绕过隐式等待?

鉴于Selenium似乎没有直接提供我想要的东西(基于Mike Kwan和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()使用上述内容至少比乱丢测试用例本身更清晰。

另请参阅以下相同方法的精细调整版本的答案:

  • 使用try-finally将隐式等待重新打开
  • 使用By locator作为参数

我还建议将参数更改为“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); 

我的实施:

 using (driver.NoImplicitWait()) { .... } 

使用扩展方法:

 public static NoImplicitWait NoImplicitWait(this IWebDriver driver) { return new NoImplicitWait(driver); } 

和class级:

 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)); } } 

@Jonic的答案帮助了我,但是我会在finally块中添加一个try { } finally { }并调用turnOnImplicitWaits()来确保它总是重新开启。

 protected boolean isElementHiddenNow(String id) { turnOffImplicitWaits(); boolean result = false; try { result = ExpectedConditions.invisibilityOfElementLocated(By.id(id)).apply(driver); } finally { turnOnImplicitWaits(); } return result; } 

我的方法是完全绕过Implicit等待并在我自己的findElement()findElements()方法中重新实现它(添加可见性检查等),我现在默认使用它。 这样,当我想立即检查某些内容时,我可以调用原始的WebDriver方法,当然不会等待。

在一个现有的代码中,很多依赖于隐式等待的思维方式,并且没有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")