将隐式等待和显式等待结合在一起会导致意外的等待时间

Posted

技术标签:

【中文标题】将隐式等待和显式等待结合在一起会导致意外的等待时间【英文标题】:Combining implicit wait and explicit wait together results in unexpected wait times 【发布时间】:2013-02-16 08:49:52 【问题描述】:

我的两个场景——

1) 首先

@driver.manage.timeouts.implicit_wait = 30
@wait = Selenium::WebDriver::Wait.new(:timeout => 45) # Time greater than implicit
@wait.until @driver.find_element(:tag_name => "body").text.include?("hey")

这让驱动程序有 45 秒的时间来搜索文本(这是预期的)

2) 第二个

@driver.manage.timeouts.implicit_wait = 30
@wait = Selenium::WebDriver::Wait.new(:timeout => 5) # Time less than implicit
@wait.until @driver.find_element(:tag_name => "body").text.include?("hey")

这现在让驱动程序 30 秒 来搜索文本(不是预期的)

有没有办法让 selenium 只等待 explicit 等待时间而不是两者中的较大者?

注意 - 不声明隐式等待时间不是一种选择,因为每次驱动程序无法找到某些东西时,我都无法让 selenium 挂起。

使用 Selenium 版本 30、windows、ff

【问题讨论】:

The default setting is 0 根据隐式等待文档,那么这里到底有什么问题? 为什么不把隐式等待也设置为 5? 隐式等待帮助我对每个元素保持默认等待,因此不要将其保持在 5 秒以下。我想使用更短的等待时间(比如“wait_to_fail”)来检查元素 not 存在。 默认不是0。默认是30,你可以在com.thoughtworks.selenium.webdriven.WebDriverCommandProcessor.java类的第60行看到。旅鼠从哪里得到“0”? selenium web driver - explicit wait vs implicit wait 的可能重复项 【参考方案1】:

不要混合隐式和显式等待。部分问题在于隐式等待通常(但可能并不总是!)在 WebDriver 系统的“远程”端实现。这意味着它们被“嵌入”到 IEDriverServer.exe、chromedriver.exe、安装到匿名 Firefox 配置文件中的 WebDriver Firefox 扩展以及 Java 远程 WebDriver 服务器 (selenium-server-standalone.jar)。显式等待仅在“本地”语言绑定中实现。使用 RemoteWebDriver 时事情会变得更加复杂,因为您可能会多次使用系统的本地端和远程端。

这就是它的工作方式:本地代码 -> Java 远程服务器 -> 远程服务器上的本地 Java 语言绑定 -> “远程”组件,如 Firefox 扩展、chromedriver.exe 或 IEDriverServer.exe。在网格的情况下它甚至更复杂,因为中间可能有其他跃点。

因此,当您尝试混合使用隐式等待和显式等待时,您会误入“未定义行为”。您可能能够弄清楚该行为的规则是什么,但随着驱动程序的实现细节发生变化,它们会发生变化。所以不要这样做。

如果您不使用隐式等待,则当找不到元素时,您不应该遇到“挂起”。驱动程序应立即引发 NoSuchElement 异常。

【讨论】:

感谢您的回复。所以问题确实在于我的脚本挂起而不是立即失败。这会是 selenium webdriver ruby​​ 问题吗? 您的意思是说,当未设置隐式等待(或设置为零)时,您的 WebDriver 代码会无限期挂起?使用 Firefox 时这些症状确实存在问题,但在 2.30.0 中已修复。如果您将隐式等待设置为零以外的任何值,那么是的,如果元素不存在,WebDriver 当然会“挂起”直到超时。当您使用其他浏览器时会发生什么?更新到 2.31 怎么样? 我发了一个related question(我对此感到困惑) @JimEvans,精彩的解释。您能帮我找到有关隐式和显式等待及其实现的更多详细信息的资源吗?到目前为止,我只能找到有关此主题的基本文档。 很棒的信息,由于不清楚,我正在向文档提交更新:code.google.com/p/selenium/issues/…【参考方案2】:

最佳实践是在每次测试开始时设置implicitlyWait(),并使用WebDriverWait() 等待元素或AJAX 元素加载。

但是,implicitlyWait() 和 WebDriverWait() 在同一个测试中不能很好地协同工作。 您必须在调用 WebDriverWait 之前取消 implicitlyWait(),因为 implicitlyWait() 还设置“driver.findElement()”等待时间。

当您使用 WebDriverWait() 时已经设置了一些初始值,请按照以下步骤操作 -

    隐式地取消Wait() 执行WebDriverWait(),并返回元素 再次隐式重置Wait()

示例 Java 代码 -

driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); //nullify implicitlyWait() 

WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds); 
element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));

driver.manage().timeouts().implicitlyWait(DEFAULT_WAIT_4_PAGE, TimeUnit.SECONDS); 

【讨论】:

你应该添加代码的来源,因为是复制的代码而不是你的。

以上是关于将隐式等待和显式等待结合在一起会导致意外的等待时间的主要内容,如果未能解决你的问题,请参考以下文章

Selenium 隐式和显式等待,未找到超时异常元素

爬虫之selenium和webdriver—基础:操作cookie和显式等待与隐式等待

Python+Selenium笔记:元素等待机制

元素操作

隐式 vs 显式 vs Fluent 等待

selenium 显示等待和隐式等待哪个更好