【发布时间】:2015-04-23 20:52:20
【问题描述】:
implicitwait()、explicitwait() 和 fluentwait() 之间的确切区别是什么?可以举例说明吗?
【问题讨论】:
implicitwait()、explicitwait() 和 fluentwait() 之间的确切区别是什么?可以举例说明吗?
【问题讨论】:
我发布了a blog article about this,我想我提供了一些其他答案错过的非常详细的信息。
隐式等待:在隐式等待期间,如果 Web 驱动程序由于其可用性而无法立即找到它,则 Web 驱动程序将定期轮询 DOM(以 0.5 秒的间隔或取决于在驱动程序浏览器实现上),直到达到默认的隐式最大等待时间。一旦指定的隐式等待最大时间结束,它将尝试在最后一次搜索元素之前抛出一个 WebDriverException,例如 NoSuchElementException。 默认设置为 0,这意味着对 driver.findElement 的调用不需要轮询 DOM,如果元素确实存在,它将在 0-999 毫秒内立即返回,否则它会抛出一个NoSuchElementException 如果在同一时间段内不存在。要覆盖默认的最大时间,请执行以下操作:
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
显式等待:在某些情况下,特定元素的加载时间可能超过一秒或更长。在这种情况下,您绝对不想设置一个巨大的隐式等待时间,因为如果您这样做了,那么您的浏览器将等待每个驱动程序调用以找到一个元素的最长时间。因此,您可能会注意到测试性能略有下降。
为避免这种情况,您只需在所需元素上定义单独的等待时间即可。通过遵循此规则,您的浏览器隐式等待时间对于每个驱动程序调用以查找一个元素来说会很短,而对于一个特定元素的具体情况,它可能会很长。
显式等待总是首先定义一个 FluentWait,例如 WebDriverWait 对象,然后通常使用预期条件来解决等待。
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id(“aId”)));
Fluent Wait:假设您有一个元素有时只需要 1 秒就出现,有时需要几分钟才能出现。在这种情况下,最好使用 FluentWait 定义显式等待,因为它会一次又一次地尝试查找元素,直到找到它或直到最终计时器用完。 WebDriverWait 是 FluentWait 的一种,因为 WebDriverWait 扩展了 FluentWait 并具有 FluentWait 类的所有功能,例如能够调整 DOM 轮询间隔,忽略异常。
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(timeoutSeconds, TimeUnit.SECONDS)
.pollingEvery(500, TimeUnit.MILLISECONDS)
.ignoring(NoSuchElementException.class);
【讨论】:
ImplicitWait 是配置 WebDriver 实例的实现,即 driver 以在一定时间内轮询 HTML DOM ( NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS、MINUTES、HOURS 或 DAYS) 在尝试查找一个或多个元素(如果它们不是立即可用)时。默认设置为0,这意味着driver 当找到查找一个或多个元素的指令时,搜索开始并且结果立即可用。
在这种情况下,在重新加载网页后,一个或多个元素可能会/可能不会在立即搜索中找到。因此,您的 Automation Script 可能会遇到以下任何异常:
因此我们引入 ImplicitWait。通过引入 ImplicitWait,驱动程序 将轮询 HTML DOM 以查找元素或元素的配置时间量。到那时,您一直在寻找的一个或多个元素可能在 HTML DOM 中可用。在您的代码中,您已经将 ImplicitWait 设置为 10 秒的值,驱动程序 将轮询 HTML DOM 10 秒。
Python:
driver.implicitly_wait(10)
Java:
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
最后,一旦你设置了 ImplicitWait,WebDriver 实例,即 driver 就能够携带这个配置直到它的生命周期。但是,如果您需要更改 WebDriver 实例的粗略时间,即 driver 等待,那么您可以重新配置它,如下所示:
Python:
driver.implicitly_wait(5)
Java:
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
如果您想在任何时候取消 ImplicitWait,您可以按如下方式重新配置它:
Python:
driver.implicitly_wait(0)
Java:
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
Fluent Wait 是Wait 接口的实现,通过它我们可以动态配置超时和轮询间隔。 FluentWait 的实例可以定义为配置等待条件的最长时间以及必须检查条件的频率。用户还可以配置等待以在等待元素时忽略特定类型的异常,例如页面上的NoSuchElementExceptions。
用法:
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("foo"));
}
});
ExplicitWait 俗称WebDriverWait 是FluentWait 的专门实现,用户可以通过它定义、配置和实现WebDriver 实例等待某个在继续执行下一行代码之前要满足的条件。有一些方法可以帮助我们实现 ExplicitWait,它只会等待所需的时间。 WebDriverWait 结合 ExpectedCondition 是 ExplicitWait 可以实现的方式之一。
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
.
.
.
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("element_xpath")));
element.click();
ExplicitWait 的这个实现在抛出 TimeoutException 之前最多等待 10 秒,或者如果它找到元素,那么它将在 0 到 10 秒内返回。 WebDriverWait 默认每 500 毫秒调用一次 ExpectedCondition,直到它成功返回。 ExpectedCondition 函数类型的成功返回值是 Boolean 值为 true 或非空对象。
在为Testing Web/Mobile Applications 自动化 Web 浏览器时,经常会遇到一些情况。 Java、C# 和 Python 绑定包含这些方便的方法,因此我们不必自己编写 ExpectedCondition 类或为它们创建自己的实用程序包。一些预期条件是:
alertIsPresent()elementToBeClickable(locator)elementToBeSelected(WebElement)frameToBeAvailableAndSwitchToIt(locator)invisibilityOf(element)你可以在这里找到Expected Conditions支持的所有方法。
【讨论】:
隐式等待:
隐式等待是告诉 WebDriver 在尝试查找某个元素时轮询 DOM 一段时间(如果它们不是立即可用)。WebDriver 将等待提到的时间,并且在此期间不会再次尝试查找该元素指定的时间段。一旦指定的时间结束,它会在抛出异常之前的最后一次尝试再次搜索元素。主要缺点是时间很长,因为驱动程序在继续之前等待指定的时间
显式等待
在这种情况下,加载特定元素的时间可能超过一分钟,您可以简单地仅在所需元素上单独设置时间。通过遵循此操作,您的浏览器隐式等待时间对于每个元素都会很短,而对于特定元素会很长。默认轮询周期为 500 毫秒,即)它将每 500 毫秒间隔检查一次元素。
流畅的等待 如果您有一个元素有时会在 1 秒内出现,而有时需要几分钟才能出现。在这种情况下,最好使用 fluent wait,因为这会一次又一次地尝试查找元素,直到找到它或直到最终计时器用完。您可以在 fluent wait 中设置轮询时间 用户还可以配置等待以忽略特定类型的异常,例如 NosuchElementException
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("foo"));
}
})
【讨论】:
显式等待是您定义的代码,用于等待特定条件发生,然后再继续执行代码。最坏的情况是Thread.sleep(),它将条件设置为要等待的确切时间段。提供了一些方便的方法来帮助您编写只等待所需时间的代码。 WebDriverWait 结合ExpectedCondition 是可以实现的一种方式。示例如下:
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));
但是,根据不同的语言实现会有所不同。有关ExpectedCondition 接口的更多信息,请参见here
隐式等待是告诉WebDriver 轮询DOM 在尝试查找一个或多个元素时(如果它们不是立即可用)一段时间。默认设置为 0。一旦设置,就会在 WebDriver 对象实例的生命周期内设置隐式等待。下面是一个隐式等待的实现:
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
这两个定义都来自seleniumhq 和最完美的定义。
Fluent Wait 只是另一种等待元素的机制。它提供了一些独特的机制来轮询DOM 以查找元素。它提供的最大功能之一是等待忽略某些exceptions 的元素。见this
【讨论】:
隐式等待:隐式等待告诉 Web 驱动程序在尝试查找元素时等待每个实例。这就像全局等待所有 driver.findelement 实例。它将强制 Web 驱动程序等待元素出现在页面上或定义最早的时间。缺点是即使在定义的时间跨度内元素未加载到页面上也会引发异常。
显式等待:显式等待有两种类型:
都是类,都实现了Wait接口。
WebDriverWait 应用于具有定义的预期条件和时间的特定元素。此等待仅适用于指定元素。当未找到元素时,此等待也可能引发异常。
WebDriverWait wait = new WebDriverWait (driver, 20);
wait.until(ExpectedConditions.VisibilityofElementLocated(By.xpath(""//button[@value='Save Changes']"")));
流畅等待:流畅等待是另一种类型的显式等待,您可以定义轮询并忽略异常以在未找到元素的情况下继续执行脚本。
new FluentWait<WebDriver>(driver).withTimeout(30, TimeUnit.SECONDS).pollingevery(10, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
【讨论】:
我认为 ExplicitWait (WebDriverWait) 和 FluentWait 之间没有太大区别。因为 WebDriverWait 是 FluentWait 的子类,所以 FluentWait 可以做的一切都可以通过 WebDriverWait 实现。
WebDriverWait 还可以设置轮询时间、最长等待时间和忽略任何异常。
【讨论】: