Skip to content

Wait until does not contain element always waits for full amount of wait time #1364

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
bartkl opened this issue Mar 29, 2019 · 9 comments
Open

Comments

@bartkl
Copy link

bartkl commented Mar 29, 2019

Hello,

A colleague of mine stumbled upon this, and I found it to be worthy of creating an issue.

Let's say implicit wait is set to 20s, and suppose I want to wait for the disappearance of the element iDontExist:

*** Settings ***
Library  SeleniumLibrary  implicit_wait=20.0

*** Test Cases ***
Testing implicit wait
    Open browser  http://www.google.com  chrome
    Wait until page does not contain element  //iDontExist

This will result in a full 20 seconds wait until it returns successfully. I inspected the code responsible, and indeed, it reflects the finding exactly:

@keyword
def wait_until_page_does_not_contain_element(self, locator, timeout=None,
                                                error=None):
    """Waits until element ``locator`` disappears from current page.
    Fails if ``timeout`` expires before the element disappears. See
    the `Timeouts` section for more information about using timeouts and
    their default value and the `Locating elements` section for details
    about the locator syntax.
    ``error`` can be used to override the default error message.
    """
    self._wait_until(
        lambda: self.find_element(locator, required=False) is None,
        "Element '%s' did not disappear in <TIMEOUT>." % locator,
        timeout, error
    )

In my opinion that is not intuitive. I would expect this keyword to return as soon as the element is not found. Maybe there's use cases for the current implementation also, in which case maybe a parameter can distinguish between both behaviors or something?

I just wanted to bring this to your attention and I'm curious to the clarification.

Thanks,
Bart

My environment:

Browser: Chrome 73.0.3683.86 (64 bits)
Browser driver: ChromeDriver version 73.0.3683.68 (47787ec04b6e38e22703e856e101e840b65afe72)
Operating System: Windows 10 version 1703 (build 15063.1631)
Libraries

  • Robot Framework: 3.1.1
  • Selenium: 3.141.0
  • SeleniumLibrary: 3.3.1
  • Interpreter: Python 2.7.16 (v2.7.16:413a49145e) (64 bits)

PS Judging by the implementation I would expect this to occur regardless of using implicit or explicit wait.

@bartkl bartkl changed the title Wait until does not contain element always waits for full amount of implicit wait time Wait until does not contain element always waits for full amount of wait time Mar 29, 2019
@aaltat
Copy link
Contributor

aaltat commented Mar 29, 2019

I agree that it is not very intuitive, but there is logical explanation. SeleniumLibrary supports two type of timeouts. There is timeout which is SeleniumLibrary level timeout and there is implicit wait which is Selenium level timeout. The implicit wait will control how long Selenium will wait element to appear and by defining implicit wait, user/SeleniumLibrary gives waiting control to Selenium how long is waited to the element to appear. This will overrule the timeout which is SeleniumLibrary level timeout.

Selenium API does not contain a method which would allow to ask that element is not in the page, in the Selenium API there is only way to ask that element is in the page. Now because you are waiting that element does not appear in the page, then Selenium will always wait the implicit wait amount to element to appear.

If only timeout is defined, which is by default 5 seconds, keyword will return immediately when the element is not in the DOM.

@bartkl
Copy link
Author

bartkl commented Mar 29, 2019

I am aware of these differences between timeout and implicit_wait, but I'm surprised about the implementation of the keyword:

# ...
lambda: self.find_element(locator, required=False) is None,
# ...

But I can imagine this is not easily changed perhaps, because of the central role of the find_element method.

Okay, the most important thing to take away here is that you're saying this problem only occurs with the implicit wait, not with the timeout value? So the advice is to strategically avoid the use of implicit wait in situations where you want to wait until some element is not contained?

Maybe this should at least be documented somewhere, preferably in the keyword documentation.

@aaltat
Copy link
Contributor

aaltat commented Mar 29, 2019

1 Implementation

The find_element eventually points to ElementFinder which basically maps locator strategy to the correct Selenium API method. Just one way to for code segregation.

But I do not understand why you are surprised, could you tell more? What did you expect and why the line you see surprising?

2 timeout
Yes, you are correct, implicit wait will give control to Selenium for element waiting and only for that. And therefore keywords execution time can be longer than what is defined by the timeout argument (In the SeleniumLibrary import or by individual keywords.)

3 documentation
Documentation can be always improved, currently it is documented in here: http://robotframework.org/SeleniumLibrary/SeleniumLibrary.html#Timeouts%2C%20waits%20and%20delays How you would like to improve it?

At least link in the: See Selenium documentation for more does not anymore exist and defaults to https://www.seleniumhq.org/ which is wrong and at least that should be fixed.

@bartkl
Copy link
Author

bartkl commented Mar 29, 2019

1. Implementation
I think I understand what tripped my brain. I didn't understand why you locate the element that way, which would indeed force you to wait for the full implicit_wait seconds, but of course you have to, since you have to check for its presence and the atomic time this takes (by definition) is the implicit_wait. So I guess I understand now :).

3. Documentation
I was referring to this specific counter-intuitive caveat of the Wait until ... not ... keywords subset. Maybe a line such as: "Bear in mind that when using Wait keywords that wait for some element or text to disappear or not be present, this will internally involve locating the element and therefore this check will never return earlier than the duration of implicit_wait." or something like that. Hope I'm putting/understanding that correctly.

Thanks :)

@aaltat
Copy link
Contributor

aaltat commented Mar 29, 2019

1 Implementation
No worries, I am many times blind to these kinds of details. It is always good to discuss and have a second opinion. Also this is a thing that get's asked now and then.

3 Documentation
It would be possible to say:

The implicit wait his higher priority than timeout, because it is Selenium level timeout and therefore implicit_wait may increase the keywords execution time to be longer than the timeout argument defines.

But I am not sure which one would be better, need to give a some tough. Pointers and pull request are always welcomed.

@bartkl
Copy link
Author

bartkl commented Mar 29, 2019

Ah yes, I like how your explanation takes into account both possible waiting parameters. That's crucial!

Personally I would still find it to be clarifying if there's explicit mentioning of this counter-intuitive effect when using those Wait until ... not ... keywords, like my example explanation above. People, like I did, might not realize there's an internal call to find_element going on which adheres to the implicit_wait value (if set). They might think, like I did, that maybe some custom logic has been applied and not be aware of the effects of implicit_wait in this context.

But I think I stated my case. At the least I learned something, thanks for explanation.

@aaltat aaltat added this to the v5.0.0 milestone May 4, 2020
@aaltat aaltat modified the milestones: v4.5.0, v5.0.0 Jul 10, 2020
@aaltat aaltat modified the milestones: v5.0.0, 5.1.0 Jan 30, 2021
@aaltat aaltat modified the milestones: v5.1.0, v5.2.0 Feb 26, 2021
@mcleanmds
Copy link

I've noticed similar behaviour for Alert Should Not Be Present - without timeout argument, it now wait the full time.

This has changed since v4.4.0, and now the v5.1.3 implementatiton doesn't match the documentation for this keyword, in particular (section in bold):

timeout specifies how long to wait for the alert to appear. By default, is not waited for the alert at all, but a custom time can be given if alert may be delayed. See the time format section for information about the syntax.

@aaltat
Copy link
Contributor

aaltat commented Apr 27, 2021

I don't follow what are you saying. Could you explain your problem with an example, which shows the timeouts too?

@emanlove
Copy link
Member

Leaving note for Review Milestone .. review the documentation issue @mcleanmds points out above ..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants