前言
在使用selenium中我们遇到了,有时候一个点击查询或者其它操作需要加载等待很长的时间,我的程序就会等待一直到超时,
用户指示浏览器导航到一个页面,然后在试图查找元素时得到一个 no such element 的错误。
或者需要等待这一步骤执行完成后才能执行下一步,就需要设置超时等待了。
1、显式等待
显示等待 是Selenium客户可以使用的命令式过程语言。它们允许您的代码暂停程序执行,或冻结线程,直到满足通过的 条件 。
这个条件会以一定的频率一直被调用,直到等待超时。这意味着只要条件返回一个假值,它就会一直尝试和等待。
也就是说:暂停程序执行,直到在规定时间内找到某个元素或满足条件才会执行下一步,否则在规定时间没有直到元素会引发的 no such element 的错误。
类似线程等待,不推荐。
// 1.第一种
// 设置在抛出错误之前等待页面加载完成的时间。如果超时为负,页面加载可以是无限期的。
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
// 2.第二种
WebDriver driver = new ChromeDriver();
driver.get("https://google.com/ncr");
driver.findElement(By.name("q")).sendKeys("cheese" + Keys.ENTER);
// 初始化并等待直到元素(链接)变成可点击的-在10秒内超时
WebElement firstResult = new WebDriverWait(driver, Duration.ofSeconds(10))
// ExpectedConditions 用法详见底部文档链接,elementToBeClickable --> 表示该元素是否可点击
.until(ExpectedConditions.elementToBeClickable(By.xpath("//a/h3")));
// 打印结果
System.out.println(firstResult.getText());
// 3.第三种
// 直接睡眠,等程序执行完成后再执行下一步
Thread.sleep(10);
2、隐式等待
还有第二种区别于显示等待 类型的 隐式等待 。通过隐式等待,WebDriver在试图查找_任何_元素时在一定时间内轮询DOM。
当网页上的某些元素不是立即可用并且需要一些时间来加载时是很有用的。
默认情况下隐式等待元素出现是禁用的,它需要在单个会话的基础上手动启用。将显式等待和隐式等待混合在一起会导致意想不到的结果,
就是说即使元素可用或条件为真也要等待睡眠的最长时间。
警告: 不要混合使用隐式和显式等待。这样做会导致不可预测的等待时间。例如,将隐式等待设置为10秒,将显式等待设置为15秒,
可能会导致在20秒后发生超时。
隐式等待是告诉WebDriver如果在查找一个或多个不是立即可用的元素时轮询DOM一段时间。默认设置为0,表示禁用。
一旦设置好,隐式等待就被设置为会话的生命周期。
WebDriver driver = new FirefoxDriver();
// 隐式等待
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));
也就是说:在10秒内找到对象了就继续往下执行,如果没有找到就轮训继续寻找对象,没有找到就引发 no such element 的错误。推荐使用。
3、流利等待
流畅等待实例定义了等待条件的最大时间量和检查频率。用户可以配置等待来忽略等待时出现的特定类型的异常,例如出现的NoSuchElementException。
类似于自定义等待,代码示例:
// 等待30秒,每5秒执行一次,等待页面上出现一个元素,并检查
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofSeconds(5))
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("foo"));
}
});