9

I run nearly 30-40 test cases twice a day. And everytime some test case fails due to page load time. Infact i have explicitly mentioned Thread.sleep("2000"); wherever i feel it takes more time to load. But still some 5-6 testCases fails. How can i make my selenium to wait until the page loads ?? And what would the below code do ? driver.manage().timeouts().implicitlyWait(4000, TimeUnit.SECONDS); Will it wait for 4 seconds everytime or it sets the maximum time limit to 4 secs . I even tried this but it really slowed my test execution. I need some help.

1
  • I was facing the same problem .After entering UN and PWD ,click on Login button every input I entered got vanished.Loading time was more and finally It was not getting loggedin also. As per advice of one of my friend at work I changed that URL i was automating.and Finally everything worked fine.
    – user35992
    Dec 5, 2018 at 8:28

11 Answers 11

10

Look at the Wait commands rather than sleep - a search on this site or Google will give you lots of examples

1
  • 1
    The single most helpful method for avoiding problems like the OP has is to use a "waitForPageToLoad" method. Totally worth it. Oct 10, 2013 at 11:35
8

You can use WebDriverWait to synch with page load. Something like the following might help

WebDriverWait wait = new WebDriverWait(driver, 15); //you can play with the time integer  to wait for longer than 15 seconds.`
wait.until(ExpectedConditions.titleContains("title")); //if you want to wait for a particular title to show up

OR

wait.until(ExpectedConditions.presenseOfElementLocated(ByLocator)); //in case you want to wait for a particular element to appear on the page.`
4

A Sleep method is almost always the least acceptable way to synchronize an automated test. A better approach might be to register an event and check the event is raised when in the desired state, or use a polling loop which will can enable the test to proceed when the system is ready (e.g. an element id appears), or a timeout occurs if it takes more than a pre-determined max wait time.

0
3

Don't ever use sleep in your test. Every sleep you have indicates to a bad test design. Let's say you have a sleep of 1000ms, but it takes 1002ms to load something - your test will break. If it takes 996ms, you are wasting time. That been said, I just answered pretty much the same question in Stack Overflow - Wait for element - WebDriver - PageObject pattern.

2
  • I think you have a point . But for page load can we use WaitForPageLoad() ? . Some times due to slow network my application becomes slow or page load time gets slower . How to handle selenium in those situations ??
    – kittudk
    Sep 26, 2013 at 5:55
  • 2
    There is no such thing has "page has finised loading" unless you are serving static html. nowadays stuff getting loaded async all the time and this conception does not exist anymore. you as a tester must know when some specific stuff happens and wait for that very thing to happen before you continue. So you rather wait for (for example) a submit button to be visible and assume the page in a state so you can continue. If you run your tests thru a proxy, the browsermob has something like WaitForNetworkTrafficToStop, but i would go with WebDriverWait.
    – Erki M.
    Sep 27, 2013 at 7:50
1

This code tells Selenium to search up to 60 seconds for id-of-element to appear on the page. Once it finds the element, you can interact with it. If the element is not found within 60 seconds, a java.lang.AssertionError will be thrown with the reason being "timeout".

for (int second = 0;; second++){
        if (second >= 60)
            fail("timeout");
        try{
            if (1 == driver.findElements(By.xpath("//a[@id=\"id-of-element"]")).size()){
                driver.findElement(By.xpath("//a[@id=\"id-of-element")).click();                    
                break;
            }
        } catch (Exception e){
      }
}

As per Kate's comment, this code will not produce a wait time of 60 seconds.

To wait for an element to appear, I would use an implicit wait:

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

This means that whenever you call WaitForElement() or WaitForElements(), the driver will wait up to 60 seconds for the specified element or elements to appear. See http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp#implicit-waits and http://www.bizalgo.com/2012/01/14/timing-races-selenium-2-implicit-waits-explicit-waits/.

2
  • I don't think this is going to give you a 60 second fuse - all it's going to give is 60 iterations which take whatever time they take - to do something like this you really need to include an explicit wait call for 1 second.
    – Kate Paulk
    Sep 17, 2013 at 18:33
  • This is the best answer IMO, except you should wait for a certain date (i.e not + 60 seconds) rather than 60 counts as mentioned, and you could refactor this to a method to take the By selector and any root element or default to the driver to be able to use it as an extension method on IWebDriver or IWebElement so your driver always tries waiting for any element it accessed to be visible.
    – chrisc
    Jun 18, 2015 at 16:41
1

Simple ready2use snippet > Working perfectly for me

static void waitForPageLoad(WebDriver wdriver) {
    WebDriverWait wait = new WebDriverWait(wdriver, 60);

    Predicate<WebDriver> pageLoaded = new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver input) {
            return ((JavascriptExecutor) input).executeScript("return document.readyState").equals("complete");
        }

    };
    wait.until(pageLoaded);
}
1
  • This thread seems active since long. @kituudk - Resolved your query of page load time? Jul 6, 2016 at 6:45
0

driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS); is the correct and cleanest way of doing this in my experience. Call it once after instantiating the driver, and all subsequent calls will correctly wait for whatever timespan specified (60 seconds in this case)

It is better to be generous in timeframes for explicit waits, as lower environments can have skewed loading times, especially when it is the first couple calls to a fresh environment. That being said, 60 seconds is still on the high end for web apps.

1
  • Why not use the explicit waits and wait for a custom condition? Feb 6, 2016 at 19:41
0

Although document.readyState works most of the time, rather than relying on document.readyState, I would suggest observing which element on the page loads last. You can base the further processing on the loading of that final element

2
  • can you expand on that answer a little? Why is the other solution better? Can you give an example on implementation in the answer?
    – ECiurleo
    Sep 7, 2017 at 8:23
  • For example, say you have an HTML table that loads last on the page, take the id of that table say table1 WebDriverWait wait1 = new WebDriverWait(driver,20); wait1.until(ExpectedConditions.visibilityOf(driver.findElement(By.Id("table1"))); You can perform rest of the processing based on this. Oct 17, 2017 at 8:20
0

As in previous responses, using static "sleeps" is not good idea. WebDriver Wait(...) should be best option for you.

However you need to be extra careful about the condition, as some elements are loading in different order. In my case bests results came with asking JS is everything is in place already :) Method that perform validation:

 return ((string)Driver.ExecuteScript("return document.readyState")).Equals("complete");

Of course Driver class is a wrapper around original WebDriver's driver and to execute script I'm using:

 public object ExecuteScript(string javascriptCode, params object[] args)
        {
            return ((IJavaScriptExecutor)DriverInstanceInstance).ExecuteScript(javascriptCode, args);
        }
0

We faced this issue in our product too, with the added complication that we're using Dojo and as such have Javascript code that executes after the readystate complete change. Because of this, we have a small piece of Javascript code that we call after the onload Javascript has finished:

    /**
     * Sets the focus on a field
     */
    setFocus : function(focusedElement, defaultFocusGainedDivId) {
        // timeout needed for IE to work
        setTimeout(function() {
            focusedElement.focus();
            if ( typeof (focusedElement.select) !== "undefined") {
                // select a value in the text inputs
                // only (no combobox).
                focusedElement.select();
            }

            if(!defaultFocusGainedDivId) {
                defaultFocusGainedDivId = "defaultFocusGainedDiv";
            }

            domConstruct.create("div", {"id": defaultFocusGainedDivId,  "class": "u-display-none" }, win.body());

        }, 300, focusedElement);
    }

Then on the Selenium end, we have this code that we call when loading a new page:

private static By defaultFocusGainedBy = By.cssSelector("div#defaultFocusGainedDiv.u-display-none");


/**
 * Waits for 5 seconds for a div with id='defaultFocusGainedDiv' and css
 * class='focusGained'. This div is added after the focus is set to a page's
 * default control using js/utils/CommonUtils.js' setFocus() function.
 * 
 */
public static void waitForPageFocusGained() {
    wdWait.until(ExpectedConditions.presenceOfElementLocated(defaultFocusGainedBy));
}

This mostly fixes this issue, although you do need to have the discipline to keep using both snippets.

-1
synchronized(driver) {
      driver.wait(4000);
}
1
  • 3
    Welcome to SQA, Raman. Could you elaborate on this? As a rule of thumb, a snippet of code is less helpful than the accompanying explanation.
    – corsiKa
    Aug 19, 2013 at 14:56

Not the answer you're looking for? Browse other questions tagged or ask your own question.