什么时候使用Selenium Webdriver的显式等待与隐式等待?

我在用:

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

但是对于下面的元素,它仍然会失败

  driver.findElement(By.id("name")).clear(); driver.findElement(By.id("name")).sendKeys("Create_title_01"); 

我已经添加了等待代码:

 for (int second = 0;; second++) { if (second >= 120) fail("timeout"); try { if (isElementPresent(By.id("name"))) break; } catch (Exception e) {} Thread.sleep(1000); } 

不应该隐含的等待,等待一个元素被发现? 如果我使用显式等待,而不是我已经添加了Thread.sleep()的代码,它也会更好吗?

TL; DR:始终使用明确的等待。 忘记隐含的等待存在。


以下是显式和隐式等待之间的区别的简要说明:

显式等待:

  • logging和定义的行为。
  • 运行在selenium的本地部分(用你的代码语言)。
  • 在任何你能想到的条件下工作。
  • 返回成功或超时错误。
  • 可以定义元素的缺失为成功的条件。
  • 可以自定义重试和exception之间的延迟忽略。

隐含的等待:

  • 没有证据和实际上未定义的行为。
  • 运行在selenium的远程部分(控制浏览器的部分)。
  • 只适用于查找元素的方法。
  • 返回find的元素或(超时后)未find。
  • 如果检查元素的缺失必须一直等到超时。
  • 除全局超时之外无法自定义。

让我们看看selenium的实际源代码中显式等待和隐式等待的区别。 我从Python的python绑定中复制了代码,因为python“易于阅读”。

WebDriverWait.until()的代码(显式等待):

 def until(self, method, message=''): end_time = time.time() + self._timeout while(True): try: value = method(self._driver) if value: return value except self._ignored_exceptions: pass time.sleep(self._poll) if(time.time() > end_time): break raise TimeoutException(message) 

现在用人类语言:明确的等待期望一个方法,如果成功,返回一个真值。 然后重复执行给定的方法之间的延迟。 来自给定方法的预期错误得到抑制。 如果给定的方法返回一个真值,那么明确的等待将返回该值。 如果时间用完,则会引发超时exception。

比较WebDriver.implicitly_wait() (为简洁起见删除了注释WebDriver.implicitly_wait()的代码:

 def implicitly_wait(self, time_to_wait): self.execute(Command.IMPLICIT_WAIT, {'ms': float(time_to_wait) * 1000}) 

self.execute()WebDriver.execute() ,它调用RemoteConnection.execute() ,这反过来,据我所知,一个RPC到远程端的selenium。

用人类语言:隐含的等待发送一个消息到seleniumwebdriver的“远程端”。 selenium驱动程序的远程端是实际控制浏览器的selenium的一部分。 远程方对信息做了什么? “这取决于”。 这取决于操作系统,浏览器和selenium版本。 据我所知,不能保证具体实施的实际行为。

可能的实现是:

  • 反复尝试查找元素,直到超时。 find元素后立即返回。
  • 尝试find元素。 等到超时。 再试一次。
  • 等到超时。 尝试find元素。

请注意,隐式等待仅在查找元素方法上生效。

我没有查到selenium远端的实际源代码。 这些信息是通过阅读关于selenium中隐式和显式等待的错误报告中的注释来收集的:

我的结论是:隐含的等待是不好的。 能力是有限的。 行为是没有文档和实现的依赖。

显式的等待可以做一切隐含的等待可以和更多。 显式等待的唯一缺点是由于多个远程过程调用而造成更多的开销。 明显的等待也稍微冗长些。 但是这种冗长使得代码是明确的。 隐含的更好。 对?


进一步阅读:

你尝试过stream利的等待吗? 等待接口的实现可能有其超时和轮询间隔configuration。 每个FluentWait实例定义等待条件的最大时间量以及检查条件的频率。 此外,用户可以configuration等待,以在等待时忽略特定types的exception,例如在页面上search元素时的NoSuchElementExceptions。

看到这个链接stream利的等待说明

特别是我用这种方式stream利地等待:

 public WebElement fluentWait(final By locator){ Wait<WebDriver> wait = new FluentWait<WebDriver>(driver) .withTimeout(30, TimeUnit.SECONDS) .pollingEvery(5, TimeUnit.SECONDS) .ignoring(NoSuchElementException.class); WebElement foo = wait.until( new Function<WebDriver, WebElement>() { public WebElement apply(WebDriver driver) { return driver.findElement(locator); } } ); return foo; } ; 

正如你已经注意到stream畅的等待返回发现Web元素。 所以你只要通过按types传递定位器,然后你可以在find的网页元素上执行任何操作。

 fluentWait(By.id("name")).clear(); 

希望这可以帮助你)

隐式等待 – 这是适用于所有元素的全局设置 ,如果元素在指定时间之前出现,则脚本将开始执行,否则脚本将抛出NoSuchElementException 。 在设置方法中使用的最佳方法。 只影响By.findelement()

Thread.sleep() – 它会睡眠脚本的时间, 而不是在脚本中使用的好方法 ,因为它是没有条件的睡眠。 如果在5%的情况下2秒是不够的呢?

显式等待 :等待指定包含/属性更改。 当应用程序向系统提供AJAX调用并获取dynamic数据并在UI上呈现时更多使用。 在这种情况下, WebDriverWait是合适的。

你尝试过使用“ WebDriverWait ”吗? 我想象你想要的是这样的:

 WebDriverWait _wait = new WebDriverWait(driver, new TimeSpan(0, 0, 2)); //waits 2 secs max _wait.Until(d => d.FindElement(By.Id("name"))); //do your business on the element here :) 

根据我的理解,这很可能会做你当前的代码。 它将不断尝试该方法(同时忽略未发现的exception),直到达到超时时间,并且可以input第三个参数来指定以毫秒为单位的hibernate。 对不起,如果这是什么隐含的等待呢!

编辑:我今天做了一些阅读,并更好地理解你的问题,并意识到这正是你的隐式等待的设置应该做的。 为了防止代码本身可以帮助其他人,请留在这里。

ImplicitWait:

  1. Static Wait 2. UnConditional Wait. ( No Conditions were given) 3. Applicable throughout the program 

在java中声明隐式等待 – selenium:Seconds之后不需要括号,它不是方法

 driver.manage().timeout().implicitWait(20, TimeUnit.SECONDS); 

显式等待:

  1. dynamic等待
  2. 有条件的等待。
  3. 在整个计划中不适用

在Java Selenium中声明显式等待。

 WebDriverWait wait=new WebDriverWait(driver, 20); wait.until(somecondition); 

隐式等待用于在整个testing脚本或程序的每个连续testing步骤之间提供等待时间(例如30秒)。 下一步只有在执行完上一步之后的30秒(或任何给定的时间已过)时才执行

句法:

 WebDriver driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); 

显式等待用于暂停执行,直到满足特定条件或已定义最大时间为止。 在整个testing脚本或程序的每个连续testing步骤之间应用隐式等待,而显式等待仅应用于特定实例。

句法:

 WebDriver driver = new FirefoxDriver(); WebDriverWait wait = new WebDriverWait(driver,30);