'Implicit wait is executing after an explicit wait

I'm having a problem with my automated script using selenium+python unittest. In my setUp() I have this line:

def setUp(self):
  self.driver.implicitly_wait(10)

and in one of my pageobjects I have this method:

    def return_note_asunto(self):
      WebDriverWait(self.driver, 5).until(EC.invisibility_of_element_located(self.gw_loader))
      WebDriverWait(self.driver, 5).until(EC.presence_of_element_located(self.note_asunto))
      return self.driver.find_elements(*self.note_asunto)[0].text

The first explicit wait in the method waits for a loader to not be visible on the page. When this happens the implicit wait executes and the scripts stops 10 seconds after the loader disappears and then the script keeps running. I'm not sure why the implicit wait is executing after the loader disappears, any idea why this could be happening? From my understanding the implicit wait x seconds waiting for an object before failing the test.



Solution 1:[1]

You are very close on your expectation of the implicit wait but there's a little more to it.

According to the selenium docs wait page:

By implicitly waiting, WebDriver polls the DOM for a certain duration when trying to find any element

So it's waiting when trying to find any element. This is set once and affects every webdriver action.

To understand the behavior you're experiencing, you need to look inside the expected condition.

Going to the github source, inside the python expected conditions you have this:

def invisibility_of_element_located(locator):
    """ An Expectation for checking that an element is either invisible or not
    present on the DOM.
    locator used to find the element
    """
    def _predicate(driver):
        try:
            target = locator
            if not isinstance(target, WebElement):
                target = driver.find_element(*target)
            return _element_if_visible(target, False)
        except (NoSuchElementException, StaleElementReferenceException):
            # In the case of NoSuchElement, returns true because the element is
            # not present in DOM. The try block checks if the element is present
            # but is invisible.
            # In the case of StaleElementReference, returns true because stale
            # element reference implies that element is no longer visible.
            return True

    return _predicate

This is your problematic line: target = driver.find_element(*target).

When you execute the find_element, and your object is NOT present (because you want the element to not be present), your implicit wait results in it waiting 10 seconds before throwing the NoSuchElement and finally returning true.

Moving forwards, you potentially have a few options.

First, don't use both wait strategies. The selenium docs do say:

Warning: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example, setting an implicit wait of 10 seconds and an explicit wait of 15 seconds could cause a timeout to occur after 20 seconds.

Hardly a great option. But, thinking about it - Do you need to wait for object #1 to disappear if you have an implicit wait which will wait until object #2 is ready?

Another option, wrap your wait in your own function and set implicit wait to zero before the implicit wait and back to 10 on your way out. It's a lot of faff but it could work. I don't have an IDE to hand but give me a shout if you need support getting this idea working.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mate Mrše