WebDriver’s implicit wait and deleting elements

Syndicator

WebDriver has introduced implicit waits on functions like find_element. That means that when WebDriver cannot find an element, it will automatically wait for a defined amount of time for it to appear. 10 seconds is the default duration.

This is very useful behaviour and makes dealing with ambiguous page load events and dynamic elements far more tolerable; where it seems obvious to a human that the test should wait briefly then WebDriver does exactly that. Tests are now more patient and durable throughout tests on dynamic webpages.

However with Selenium RC and Selenium IDE we became quite used to using methods like is_element_present and wait_for_element_present to deal with Ajax and page loading events. With WebDriver we have to write them ourselves.

Checking an element is not present
When dealing with Ajax or javascript we might want to wait until an element is not present, when an element is being deleted, for example. Trying to find an element after it has been deleted will cause WebDriver to implicitly wait for the element to appear. This is not WebDriver’s fault. It’s doing the right thing, but we need to tell it not to implicitly wait just for this moment otherwise we will waste time waiting when we don’t need to. This time can really add up if you check a few times in each test.

The Web QA team has written its own is_element_present method for WebDriver:

def is_element_present(self, *locator):
    self.selenium.implicitly_wait(0)
    try:
        self.selenium.find_element(*locator)
        return True
    except NoSuchElementException:
        return False
    finally:
        # set back to where you once belonged
        self.selenium.implicitly_wait(default_implicit_wait)

There are 4 important things going on here. In order:

  1. Setting implicity_wait to 0 so that WebDriver does not implicitly wait.
  2. Returning True when the element is found.
  3. Catching the NoSuchElementException and returning False when we discover that the element is not present instead of stopping the test with an exception.
  4. Setting implicitly_wait back to 10 after the action is complete so that WebDriver will implicitly wait in future.

(Note that we have previously stored the default implicit wait value in the default_implicit_wait variable)

You may use this in logic but we mostly use this in WebDriverWait. It is important for bypassing WebDriverWait’s catching of the ElementNotFoundException:
WebDriverWait(self.selenium, 10).until(lambda s: not self.is_element_present((By.ID, ‘delete-me’)))

This method works well and most importantly the implicit wait is not triggered meaning your test does not needlessly wait!