Reputation: 363
The docs say:
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.
Sub-question:
In the case of find_elements_by_
(plural), how many elements does implicit_wait
wait for to exist before continuing with your script? Or does implicit_wait
only work with find_element_by_
(singular)? If so what do the docs mean by "or elements"?
From an SO answer I read that it's best not to use both implicit and explicit waits in the same script, which I took notice of as I'd like the tests to be as robust as possible.
Since I know there are times I'll definitely need WebDriverWait
, does this mean I need to get rid of implicit_wait
in my unittest
setUp
method and instead employ WebDriverWait
every single time I use any find_element_by_
method?
(I'd rather not have to do this; although I suppose I could put each of the find_element_by_
methods in my own custom functions -each wrapped in their own WebDriverWait
-it feels like I shouldn't have to).
So my main question is:
Can I instead keep my implicit_wait
in my test setUp
method, and then only use WebDriverWait
when it comes to find_elements_by_
and other places where I know I need it?
Upvotes: 4
Views: 1753
Reputation: 151511
Since I know there are times I'll definitely need WebDriverWait, does this mean I need to get rid of implicit_wait in my unittest setUp method and instead employ WebDriverWait every single time I use any find_element_by_ method?
Yes. As you've seen in the question you link to, if you use both types of waits, you're going to run into undesirable behavior. It's not just theoretical. I've experienced that behavior first hand, tried to debug it, found the question you linked to and then removed all implicit waits from my test suites.
I developed a library to help with setting up the explicit waits (and do a bunch of other things). Assuming you already have a driver
object that has the selenium web driver:
from selenium.webdriver.common.by import By
import selenic.util
util = selenic.util.Util(driver)
# This goes through util and uses the explicit wait set by util.
foo = util.find_element((By.CSS_SELECTOR, "..."))
# For special cases that take longer to give results.
with util.local_timeout(10):
# The timeout is set to 10 for calls in this with block.
bar = util.find_element(...)
# The timeout is restored to what it was just before the with.
There are some times when you don't need to use waits at all because logically if element A is present then B is also present, so you don't have to wait for it. For instance. if you want the parent of an element you've already obtained from Selenium, you can do parent = foo.find_element_by_xpath("..")
.
As for the behavior of find_elements
, it returns as soon as it determines that there is a result to return. This could mean getting only one element if later elements do show up after find_elements
has found something to return.
Upvotes: 2