使用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")