When to use explicit wait vs implicit wait in Selenium Webdriver?
Asked Answered
S

8

63

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()?

Spontoon answered 1/5, 2012 at 20:50 Comment(4)
Are you absolutely sure it fails with a NoSuchElementException? It could fail with a WebDriverException, StaleElementReferenceException, ElementNotVisibleException or something similar. I'll try to guess the first one. Implicit wait waits only until the function fires NoSuchElementExceptions...Backbone
The difference between Selenium explicit wait method and your code with Thread.sleep() is in time steps: WebDriverWait check for element presence every 500 milliseconds, your code 1000 milliseconds.Wellturned
Apologies for not stating the error. It is ElementNotVisibleExeption. But the element visible exception it complains about is some other element which cannot be clicked since the Name field is empty. I will add an explicit wait for Name field since that is the first field to be worked upon in the new page.Spontoon
I have a related question which has code from a Udemy course. The code has mixed implicit & explicit waits. It repeatedly sets implicit time out to zero before doing an explicit wait and resets implicit back after explicit wait is over. Is there a problem in this kind of mixing ? Can someone please help me ? Currently, I have offered 50 bounty for this but did not get acceptable answers. #60763406. thanks.Roar
D
125

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.

Code examples with explanation. First implicit wait:

WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));

Now explicit wait:

WebDriver driver = new FirefoxDriver();
driver.get("http://somedomain/url_that_delays_loading");
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement myDynamicElement = wait.until(
  ExpectedConditions.presenceOfElementLocated(By.id("myDynamicElement")));

Both code examples do the same thing. Find a certain element and give up if not found after 10 seconds. The implicit wait can do only this. It can only try to find an element with a timeout. The strength of explicit wait is that it can wait for all kinds of conditions. Also customize timeout and ignore certain exceptions.

Example of possible conditions: elementToBeClickable, numberOfElementsToBeMoreThan or invisibilityOf. Here is a list of the built in expected conditions: https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html

More explanations:

The implicit wait timeout has effect only on findElement* methods. If set then all findElement* will "wait" for the set time before declaring that the element cannot be found.

How a findElement* will wait is not defined. It depends on browser or operating system or version of selenium. 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.

This list is gathered from observations and reading bug reports and cursory reading of selenium source code.


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 verbose code. But that verbosity makes the code explicit. And explicit is better that implicit. Right?


Further reading:

Dalton answered 21/1, 2015 at 12:40 Comment(6)
I found implicit waits are SO much easier, especially for robots or automation scripts that run local. I used both explicit and implicit in two different projects and the implicit was so much faster to code without having to repeat myself (DRY). I had to create an API for a web app that doesn't have an API! The only problem was testing for existence of an element that may not be there. Implicit waits the full time, but I just set the timeout to 0 before the check (in a try/catch) and reset it to 5 after. That occurs much less frequently so it's worth it.Ebonize
Doesn't explicit wait take twice as much code, though? This is a pretty terrible API design.Islander
Implicit waits are only "So much easier" if your automation follows a pattern of never checking that things don't exist. It's the lazy option and it can cause lots of strange and hard to diagnose problems in the future (at which point most people moan about how shit Selenium is, not realising that it's due to their choices when creating their automation framework)Witkin
@Witkin - could you please review my answer ? thanks. https://mcmap.net/q/182978/-when-to-use-explicit-wait-vs-implicit-wait-in-selenium-webdriverNeuropathy
@Witkin - I have a related question which has code from a Udemy course. The code has mixed implicit & explicit waits. It repeatedly sets implicit time out to zero before doing an explicit wait and resets implicit back after explicit wait is over. Is there a problem in this kind of mixing ? Please help me. I have offered 50 bounty for this but did not get acceptable answers. Thanks. #60763406.Roar
@Ebonize - could you please answer this question for me #60763406 ? thank you.Roar
A
4

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)

Anear answered 3/9, 2012 at 13:24 Comment(1)
Fluent Wait is the underlying implementation of Explicit waitsWitkin
C
4

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.

Chancemedley answered 12/3, 2013 at 16:54 Comment(0)
J
2

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.

Joshi answered 1/5, 2012 at 21:56 Comment(6)
Are you sure? Which/where are the errors? I thought I ran this in my own environment and it was all fine, so would appreciate any feedback :)Joshi
E.g. method name is "findElement" not "FindElement". "=>" doesn't make sense in a Java context which is what the question is written in.Holler
@JoshDiehl The code in the answer is perfectly correct C# code. Admittedly, it would've been nice if Nashibukasan had mentioned that up front, and that the equivalent Java code would look somewhat different, but it doesn't mean the code is invalid.Cavalry
Ah! Thanks @Cavalry you are correct, I have given a very mean C# example, my apologies! I was helping someone in another thread who was coding in C# and didn't check your syntax thoroughly clearly. I will attempt to update my answer at some point today to be Java.Joshi
WebDriverWait is an explicit waitWitkin
@Joshi my code just not wait for like here 2secs and throws exception before that. Any idea?Imprimis
C
1

ImplicitWait :

    1. Static Wait 
    2. UnConditional Wait (No conditions are given)
    3. Applicable throughout the program

Declaring the implicit wait in java - selenium:

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

When to use implicit Wait?

The implicit wait is not recommended to use anywhere in the Automation suite, as this is static, and we don't know when the web element will pop up in the website.

ie. Let's say you have set implicit wait of 5 sec, and the driver is able to identify the web element in 2 seconds, as we have applied implicit wait driver will wait for 3 more seconds (till 5 seconds). This will slow down the process of automation.

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);

When to use an explicit wait?

We should always use explicit wait since it is dynamic in nature.

ie. Let's say you have set explicit wait of 5 sec, and the driver is able to identify the web element in 2 seconds, as we have applied explicit wait driver will not wait for 3 more seconds (till 5 seconds). The driver will continue after 2 seconds. This will fasten up the automation process.

Chink answered 16/5, 2017 at 18:15 Comment(2)
As per seleniumworkbench.blogspot.com/search/label/dynamic%20wait ,Implicit wait is dynamicAntipus
downvoted for misleading explanation of implicit wait, it doesn't cause every retrieval to wait for the maximum duration. If you've set implicit wait to 5 sec, element is found immediately, driver won't wait and immediately return the result, read 1-9, especially 1 and 6. It states, "If elements returned is empty and the current time is less than end time return to step 4. Otherwise, continue to the next step." w3c.github.io/webdriver/#element-retrievalMineralogy
T
0

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);
Tercentenary answered 8/8, 2017 at 6:13 Comment(0)
N
0

After looking at all the answers and comments here, I am summarizing them with some code to test the simultaneous use of both implicit and explicit waits.

  • Use implicit waits only when you (generally) don't need to check for absence of elements, for example in a throw away web scraping project.

  • Never mix implicit and explicit waits together. Refer link1 and link2. If you test for absence of an element, then wait time becomes unpredictable. In the below code, only sometimes the wait time = implicit wait. You can test for absence by simply using an invalid locator.

I have taken the code in link2 and refactored it make it short and provide a summary. The code shows the actual wait time when both implicit and explicit waits are used.

The code below goes to a website and tries to find a valid element and invalid element. It uses both implicit and explicit waits. In case of invalid element search, it tries different combinations of implicit/IW and explicit/EW wait times - IW = EW, IW > EW and IW < EW.

First, the output :

WHEN ELEMENT IS FOUND WITHOUT ANY DELAY :
>>> WITH implicit = 30, explicit = 20  :::::  Wait time = 0


WHEN ELEMENT IS NOT FOUND :
a. When implicit wait = explicit wait.
>>> WITH implicit = 10, explicit = 10  :::::  Wait time = 10. ***WITH EXCEPTION*** : NoSuchElementException

b. When implicit wait > explicit wait.
>>> WITH implicit = 30, explicit = 10  :::::  Wait time = 30. ***WITH EXCEPTION*** : NoSuchElementException

c. When implicit wait < explicit wait.
>>> WITH implicit = 10, explicit = 30  :::::  Wait time = 10. ***WITH EXCEPTION*** : NoSuchElementException

The code:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

/*
 * Facing this chromedriver error after opening browser - [SEVERE]: Timed out receiving message
 * from renderer: 0.100.
 * */
public class TimeTest {
    static final SimpleDateFormat dateFormat = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a");
    static final String URL = "https://www.redbus.in/";
    static final String TIME_ZONE_NAME = "Europe/Madrid";
    static final By validLoc = By.id("src");
    static final By inValidLoc = By.id("invalid locator");
    static WebDriver driver;

        public static void main(String[] args) {
            dateFormat.setTimeZone(TimeZone.getTimeZone(TIME_ZONE_NAME));

            //>>> Open chrome browser
            System.setProperty("webdriver.chrome.driver", "C:/drivers/chromedriver.exe");
            TimeTest.driver= new ChromeDriver();
            driver.manage().window().maximize();

            //>>> Test waiting logic.

            System.out.println("\n\nWHEN ELEMENT IS FOUND WITHOUT ANY DELAY : ");
            //mixing of implicit wait and explicit wait will not impact on webdriver behavior.
            testWait(30, 20, validLoc, "");

            System.out.println("\n\nWHEN ELEMENT IS NOT FOUND : ");
            //Run the method multiple times. Wait time generally = 10 seconds, but sometimes = 20 seconds.
            testWait(10, 10, inValidLoc, "a. When implicit wait = explicit wait.");

            //Wait time always = implicit wait. Generally ?
            testWait(30, 10, inValidLoc, "b. When implicit wait > explicit wait.");

            //Wait time always = implicit wait. Generally ?
            testWait(10, 30, inValidLoc, "c. When implicit wait < explicit wait.");

            //>>> Close the browser.
            driver.quit();
        }


        public static void testWait(int implicitWait, int explicitWait, By locator, String comment){
            // setting implicit time
            driver.manage().timeouts().implicitlyWait(implicitWait, TimeUnit.SECONDS);

            // Loading a URL
            driver.get(URL);

            // defining explicit wait
            WebDriverWait wait= new WebDriverWait(driver, explicitWait);
            // Locating and typing in From text box.


            Date start = new Date();
            String waitStats = comment + "\n>>> WITH implicit = " + implicitWait + ", explicit = " + explicitWait +
                    "  :::::  " ;//+ "Wait start = " + dateFormat.format(start)

            String exceptionMsg = "";

            try {
                WebElement fromTextBox = wait.until(ExpectedConditions.visibilityOf(driver.findElement(locator)));
            }catch (Exception ex){
                exceptionMsg = ". ***WITH EXCEPTION*** : " + ex.getClass().getSimpleName();
            }

            Date end = new Date();
            //waitStats += ", Wait end = " + dateFormat.format(end)
            waitStats += "Wait time = " +
                    TimeUnit.SECONDS.convert(end.getTime() - start.getTime(), TimeUnit.MILLISECONDS)
                    + exceptionMsg + "\n";

            System.out.println(waitStats);

        }

}
Neuropathy answered 18/3, 2020 at 19:44 Comment(3)
The behaviour of b. and c. in your example may vary based on combinations of the following: which language binding you use, which driver binary you use and which version of the previous two that you use. There is no guarantee that the result you have received from testing how b. and c. works will continue to work in that way. The behaviour is undefined and dependent upon circumstances that are outside of your control.Witkin
@Witkin - why is it so unpredictable? Is that a bug or is it a feature?Neuropathy
It's unpredictable because the behaviour has never been defined, so there are no standards to code to. It's one of the reasons people are constantly encouraged not to mix implicit and explicit waits. Implicit waits are a shortcut for the lazy, not a solution that should be used in a well written test framework.Witkin
H
0

Implicit wait:

  1. Applicable to all driver.findelement commands
  2. Cares only for the presence of the element. If the element is invisible or not interactable then it won't care about that.

Explicit Wait

  1. You can check presence, visibility , interactability and many other things - dynamically wait for these

    WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(20)); wait.until(ExpectedConditions.presenceOfElementLocatedBy(By.id("xcxcxc"));

Halmahera answered 18/8, 2020 at 11:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.