When to use explicit wait vs implicit wait in Sele

2019-01-01 06:50发布

I am using:

driver.manage().timeouts().implicitlyWait(180, TimeUnit.SECONDS);

But it still fails continuously for the below element

    driver.findElement(By.id("name")).clear();
    driver.findElement(By.id("name")).sendKeys("Create_title_01");

I have added wait code:

for (int second = 0;; second++) {
        if (second >= 120) fail("timeout");
        try { if (isElementPresent(By.id("name"))) break; } catch (Exception e) {}
        Thread.sleep(1000);
    }

Shouldn't implicit wait take care of waiting till an element is found? Also would it be better if I use Explicit wait instead of the code I have added that has Thread.sleep()?

6条回答
ら面具成の殇う
2楼-- · 2019-01-01 07:28

Implicit waits are used to provide a waiting time (say 30 seconds) between each consecutive test steps across the entire test script or program. Next step only executed when the 30 Seconds (or whatever time is given is elapsed) after execution of previous step

Syntax:

WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);

Explicit waits are used to halt the execution till the time a particular condition is met or the maximum time which is defined, has elapsed. Implicit wait has applied between each consecutive test steps across the entire test script or programs while Explicit waits are applied for a particular instance only.

Syntax:

WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver,30);
查看更多
荒废的爱情
3楼-- · 2019-01-01 07:38

TL;DR: Always use explicit wait. Forget that implicit wait exists.


Here is a quick rundown on the differences between explicit and implicit wait:

Explicit wait:

  • documented and defined behaviour.
  • runs in the local part of selenium (in the language of your code).
  • works on any condition you can think of.
  • returns either success or timeout error.
  • can define absence of element as success condition.
  • can customize delay between retries and exceptions to ignore.

Implicit wait:

  • undocumented and practically undefined behaviour.
  • runs in the remote part of selenium (the part controlling the browser).
  • only works on find element(s) methods.
  • returns either element found or (after timeout) not found.
  • if checking for absence of element must always wait until timeout.
  • cannot be customized other than global timeout.

Let's see the difference between explicit wait and implicit wait in the actual source code of selenium. I copied the code from the python binding of selenium because python is "easy to read".

The code of WebDriverWait.until() (explicit wait):

def until(self, method, message=''):
    end_time = time.time() + self._timeout
    while(True):
        try:
            value = method(self._driver)
            if value:
                return value
        except self._ignored_exceptions:
            pass
        time.sleep(self._poll)
        if(time.time() > end_time):
            break
    raise TimeoutException(message)

Now in human language: explicit wait expects a method which returns a truish value if successful. It then repeatedly executes the given method with a delay in between. Expected errors from the given method are supressed. If the given method returns a truish value then explicit wait will return that value. If the time runs out a timeout exception is raised.

Compare to the code of WebDriver.implicitly_wait() (comments removed for brevity):

def implicitly_wait(self, time_to_wait):
    self.execute(Command.IMPLICIT_WAIT, {'ms': float(time_to_wait) * 1000})

self.execute() is WebDriver.execute() which calls RemoteConnection.execute() which in turn does, as far as I can tell, an RPC to the remote side of selenium.

In human language: the implicit wait sends a message to the "remote side" of the selenium webdriver. The remote side of the selenium webdriver is the part of selenium which is actually controlling the browser. What does the remote side do with the message? "It depends". It depends on the operating system and on the browser and on the version of selenium. As far as I can tell there is no guarantee about the actual behaviour of a specific implementation.

Possible implementations are:

  • repeatedly try to find element until timeout. return as soon as element is found.
  • try to find element. wait until timeout. try again.
  • wait until timeout. try to find element.

Note that implicit wait only takes effect on find element(s) methods.

I have not looked up the actual source code of the remote sides of selenium. The information is gathered from reading the comments in the bug reports about implicit and explicit wait in selenium:

My conclusion: Implicit wait is bad. The capabilities are limited. The behaviour is undocumented and implementation dependent.

Explicit wait can do everything implicit wait can and more. The only disadvantage of explicit wait is a bit more overhead because of multiple remote procedure calls. Also the explicit wait is a bit more verbose. But that verbosity makes the code explicit. And explicit is better that implicit. Right?


Further reading:

查看更多
君临天下
4楼-- · 2019-01-01 07:38

Have you tried using 'WebDriverWait' ? I imagine what you want is this:

WebDriverWait _wait = new WebDriverWait(driver, new TimeSpan(0, 0, 2)); //waits 2 secs max
_wait.Until(d => d.FindElement(By.Id("name")));
//do your business on the element here :)

This pretty much will, to my understanding, do what your current code is. It will constantly try the method (while ignoring not found exceptions) until the timeout of the passed in timespan is reached and a third parameter can be entered to specify the sleep in milliseconds. Sorry if this is what implicitlyWait does too!

Edit: I did some reading today and understand your question better and realise that this does exactly what your setting of implicit wait should do. Will leave it here just in case the code itself can help someone else.

查看更多
零度萤火
5楼-- · 2019-01-01 07:41

Have you tried fluentWait? An implementation of the Wait interface that may have its timeout and polling interval configured on the fly. Each FluentWait instance defines the maximum amount of time to wait for a condition, as well as the frequency with which to check the condition. Furthermore, the user may configure the wait to ignore specific types of exceptions whilst waiting, such as NoSuchElementExceptions when searching for an element on the page.

see this link fluent wait description

In particular I used fluent wait in this way:

public WebElement fluentWait(final By locator){
        Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
                .withTimeout(30, TimeUnit.SECONDS)
                .pollingEvery(5, TimeUnit.SECONDS)
                .ignoring(NoSuchElementException.class);

        WebElement foo = wait.until(
new Function<WebDriver, WebElement>() {
            public WebElement apply(WebDriver driver) {
                        return driver.findElement(locator);
                }
                }
);
                           return  foo;              }     ;

As you've noticed fluent wait returns found web element. So you simply pass the locator with By type and then you can perform any actions on the found web element.

fluentWait(By.id("name")).clear();

Hope this helps you)

查看更多
其实,你不懂
6楼-- · 2019-01-01 07:42

ImplicitWait :

    1. Static Wait 
    2. UnConditional Wait. ( No Conditions were given)
    3. Applicable throughout the program

Declaring the implicit wait in java - selenium:

driver.manage().timeout().implicitWait(20, TimeUnit.Seconds());

Explicit Wait:

  1. Dynamic Wait
  2. Conditional Wait.
  3. Not applicable throughout the program

Declaring the Explicit Wait in Java Selenium.

WebDriverWait wait=new WebDriverWait(driver, 20); wait.until(somecondition);
查看更多
墨雨无痕
7楼-- · 2019-01-01 07:47

Implicit wait - It's global setting applicable for all elements and if element appear before specified time than script will start executing otherwise script will throw NoSuchElementException. Best way to use in setup method. Only affect By.findelement().

Thread.sleep() - It will sleep time for script, not good way to use in script as it's sleep without condition. What if 2 seconds are not enough in 5% of the cases?

Explicit wait: Wait for specify contains/attribute change. More used when application gives AJAX call to system and gets dynamic data and render on UI. In this case WebDriverWait is suitable.

查看更多
登录 后发表回答