Selenium webdriver:驱动程序尝试查找具有隐式等待超时的元素多少次?

Selemium webdriver: How many times does a driver try to find element with an implicit wait timeout?

假设我有这样的代码:

Webdriver driver = new ChromeDriver();
driver.manage().timeout().implicitWait(10, TimeUnit.SECONDS);
driver.findElement(By.id("nothing"));

我无法理解 Selenium 文档中的这一行:隐式等待是告诉 WebDriver 在尝试查找一个或多个元素(如果它们不是立即可用的情况下)时轮询 DOM 一段时间.

那么这是否意味着驱动程序会等待 10 秒才能首次尝试找到该元素?还是说驱动会先找元素,没找到就等10秒,再找,没找到就抛超时异常?驱动程序总共尝试查找元素两次?

您实际上可以通过将 JSON Wire protocol commands 记录到 Chrome 服务日志 中来解决问题。假设我们有这个 Python 代码(为了举例):

from selenium import webdriver

driver = webdriver.Chrome(service_log_path="/tmp/log")
driver.get("http://www.google.com")

driver.find_element_by_css_selector("strange.non.existing.element")

driver.quit()

这里我们立即得到 NoSuchElementException,在 /tmp/log 中我们有:

[2.134][INFO]: COMMAND Navigate {
   "sessionId": "920fbde18d13995672cbbdd0a15e905a",
   "url": "http://www.google.com"
}
[2.195][INFO]: Waiting for pending navigations...
[2.239][INFO]: Done waiting for pending navigations
[2.593][INFO]: Waiting for pending navigations...
[3.704][INFO]: Done waiting for pending navigations
[3.704][INFO]: RESPONSE Navigate
[3.706][INFO]: COMMAND FindElement {
   "sessionId": "920fbde18d13995672cbbdd0a15e905a",
   "using": "css selector",
   "value": "strange.non.existing.element"
}
[3.706][INFO]: Waiting for pending navigations...
[3.706][INFO]: Done waiting for pending navigations
[3.720][INFO]: Waiting for pending navigations...
[3.720][INFO]: Done waiting for pending navigations
[3.720][INFO]: RESPONSE FindElement no such element
  (Session info: chrome=43.0.2357.134)

现在,让我们将隐式等待设置为 10 秒:

from selenium import webdriver

driver = webdriver.Chrome(service_log_path="/tmp/log")
driver.get("http://www.google.com")

# setting the implicit wait
driver.implicitly_wait(10)

driver.find_element_by_css_selector("strange.non.existing.element")

driver.quit()

现在,如果我们查看日志:

[1.996][INFO]: COMMAND Navigate {
   "sessionId": "657700804d0d8f71b2bfee6dc222c289",
   "url": "http://www.google.com"
}
[2.073][INFO]: Waiting for pending navigations...
[2.106][INFO]: Done waiting for pending navigations
[2.477][INFO]: Waiting for pending navigations...
[3.371][INFO]: Done waiting for pending navigations
[3.371][INFO]: RESPONSE Navigate
[3.374][INFO]: COMMAND SetImplicitWait {
   "ms": 10000.0,
   "sessionId": "657700804d0d8f71b2bfee6dc222c289"
}
[3.374][INFO]: RESPONSE SetImplicitWait
[3.376][INFO]: COMMAND FindElement {
   "sessionId": "657700804d0d8f71b2bfee6dc222c289",
   "using": "css selector",
   "value": "strange.non.existing.element"
}
[3.376][INFO]: Waiting for pending navigations...
[3.376][INFO]: Done waiting for pending navigations
[13.410][INFO]: Waiting for pending navigations...
[13.410][INFO]: Done waiting for pending navigations
[13.410][INFO]: RESPONSE FindElement no such element
  (Session info: chrome=43.0.2357.134)

因为,您可以看到只有一个 FindElement 命令发送到 WebDriver,但响应返回并且仅在 10 秒延迟后才抛出 NoSuchElementException


内部发生的事情是 described in the docs here:在 10 秒内它轮询 DOM 试图找到忽略 NoSuchElementException 的所需元素。当时间到了但还没有找到元素时,它会抛出 NoSuchElementException:

An implicit wait is to tell WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object instance.

如果元素driver.findElement(By.id("nothing"));在您的网页中可用,它将找到网络元素并继续下一个代码。如果该网页元素不存在于网页中,则 driver 将等待 10 秒,因为您给出的是隐式等待 10 秒。最后测试将失败,因为找不到元素。所以只有一次 driver 尝试找到网络元素。