You can actually clear things up by logging the JSON Wire protocol commands into the Chrome service logs. Let's say we have this Python code (for the sake of an example):
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()
Here we get a NoSuchElementException
instantly and in /tmp/log
we have:
[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)
Now, let's set the Implicit Wait to 10 seconds:
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()
Now, if we would look into logs:
[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)
As, you can see there was only one FindElement
command sent to the WebDriver, but the response got back and the NoSuchElementException
was thrown only after a 10 seconds delay.
What happens internally is described in the docs here: for the 10 seconds it polls the DOM trying to find the desired element ignoring NoSuchElementException
. When time is up and no element found yet it would throw 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.