Selenium WebDriver: Waiting for an application to be fully loaded

While working with Selenium WebDriver to automate web application tests in multiple browsers and application platforms, we found out some cases in which the application under test was not fully loaded when our tests executed, causing the test with the first browser to fail (but not the subsequent ones).

For example, when using Cargo to provision an embedded JBoss container, the ‘server ready’ flag was sent once the HTTP services were available, but the application was not loaded until first request hit the server.

After unsuccessfully trying with some Cargo settings, we considered adapting the test script to handle this.

To our surprise, the WebDriver API provided us with a very elegant, minimally disruptive, way of handling with this situation.

In previous posts we were simply using a pattern like this one to load a page, find a link and click on it:

driver.get(baseUrl);
driver.findElement(By.linkText("Find owner")).click();

In those posts we also used another pattern for waiting a page to be loaded after a link click or form submit:

(new WebDriverWait(driver, 5)).until(new ExpectedCondition<Boolean>() {
    public Boolean apply(WebDriver d) {
        return d.getCurrentUrl().startsWith(baseUrl + "/owners/search");
    }
});

Up to here, nothing new. WebDriverWait and ExpectedCondition allows for defining a wide range of conditions, like waiting for a new page to become available, waiting for a new field to be enabled or waiting for some AJAX response to be received. Combining the previous two snippets, we can write a condition that reads as: try loading this page until it contains a link with the text “Find owner”, but do not wait for more than five seconds. Here is the code we used:

// wait for the application to get fully loaded
WebElement findOwnerLink = (new WebDriverWait(driver, 5)).until(new ExpectedCondition<WebElement>() {
    public WebElement apply(WebDriver d) {
        d.get(baseUrl);
        return d.findElement(By.linkText("Find owner"));
    }
});

findOwnerLink.click();

With this small change in code, the test script waits until the application is fully loaded and the first page in the test sequence is available.

... Cargo output provisioning the server and JBoss starting up

[INFO] [talledLocalContainer] 09:20:06,004 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) JBAS015876: S
tarting deployment of "petclinic.war"
[INFO] [talledLocalContainer] 09:20:06,004 INFO [org.jboss.as.server.deployment] (MSC service thread 1-3) JBAS015876: S
tarting deployment of "cargocpc.war"
[INFO] [talledLocalContainer] 09:20:07,779 INFO [org.jboss.web] (MSC service thread 1-5) JBAS018210: Registering web co
ntext: /cargocpc
[INFO] [talledLocalContainer] JBoss 7.1.1.Final started on port [8180]

... JBoss Cargo adapter sends the 'ready' flag at this point

[INFO]
[INFO] --- maven-failsafe-plugin:2.8.1:integration-test (integration-test) @ org.springframework.samples.petclinic-rhc -
--
[INFO] Failsafe report directory: C:\projects\deors.demos\petclinic\org.springframework.samples.petclinic-rhc\target\fai
lsafe-reports
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running org.springframework.samples.petclinic.it.NewPetFirstVisitIT

... Test script is waiting!

[INFO] [talledLocalContainer] 09:20:12,521 INFO [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-1) JBAS01
0404: Deploying non-JDBC-compliant driver class com.mysql.jdbc.Driver (version 5.1)
[INFO] [talledLocalContainer] 09:20:12,605 INFO [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/pe
tclinic]] (MSC service thread 1-2) Initializing Spring root WebApplicationContext
[INFO] [talledLocalContainer] 09:20:12,608 INFO [org.springframework.web.context.ContextLoader] (MSC service thread 1-2
) Root WebApplicationContext: initialization started
[INFO] [talledLocalContainer] 09:20:12,648 INFO [org.springframework.web.context.support.XmlWebApplicationContext] (MSC
 service thread 1-2) Refreshing Root WebApplicationContext: startup date [Fri Jan 11 09:20:12 CET 2013]; root of context
 hierarchy
[INFO] [talledLocalContainer] 09:20:12,704 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] (MSC se
rvice thread 1-2) Loading XML bean definitions from ServletContext resource [/WEB-INF/classes/applicationContext-jdbc.xm
l]
[INFO] [talledLocalContainer] 09:20:13,037 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] (MSC se
rvice thread 1-2) Loading XML bean definitions from ServletContext resource [/WEB-INF/classes/applicationContext-dataSou
rce.xml]

... Rest of JBoss and Pet Clinic initialization - test is waiting for the app to be available

[INFO] [talledLocalContainer] 09:20:16,743 INFO [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deplo
yed "petclinic.war"
[INFO] [talledLocalContainer] 09:20:16,744 INFO [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deplo
yed "cargocpc.war"
Tests run: 6, Failures: 0, Errors: 0, Skipped: 5, Time elapsed: 11.745 sec

... The test executed successfully (some browsers skipped)

Out of curiosity, this does not happen with Cargo and Tomcat/Jetty, but it did no harm to add the wait!

Happy testing!

P.S.: More on WebDriver waits here:  http://seleniumhq.org/docs/04_webdriver_advanced.jsp

3 thoughts on “Selenium WebDriver: Waiting for an application to be fully loaded

Leave a comment