Performance Zone is brought to you in partnership with:

Tom is a passionate Java/JEE developer working remotely from home located in Poland. He is a big fan of Apache Wicket, clean code, testing and methods with names that actually say something. In his free time he blogs, tweets and organizes Confitura, the biggest Java conference in Poland. Privately husband, father and dog owner, he likes to watch and play football (soccer if you're from USA). Tomasz is a DZone MVB and is not an employee of DZone and has posted 14 posts at DZone. You can read more from them at their website. View Full User Profile

Reusing browser instance in Geb UI tests

05.14.2013
| 1333 views |
  • submit to reddit

Geb is next-generation UI testing library that frees developer from dealing with Selenium API which is in many cases not so friendly. The most important feature of Geb is its support, or I would even say, strong encouragement to use Page Objects in your UI tests. Page Objects are also present in Selenium, but they are not as intuitive and east to use as in Geb.
But enough about Geb itself. Today I will share with you simple trick how to share one browser instance when running many Geb UI tests. This will significantly reduce time needed to execute UI tests and also reduce memory usage on test machines.

The Problem

Assume we have many test classes (spefications) similar to this one below.

class ExampleUITest extends GebSpec {
 
    def "Should test feature 1"() {
        given:
        to LoginPage
 
        when:
        loginWith("login", "password")
 
        then:
        at HomePage
        assert loggedUserLabel == "loggedUser"
    }
 
    def "Should test feature 2"() {
        given:
        to LoginPage
 
        when:
        loginWith("login", "password")
 
        then:
        at HomePage
        assert loggedUserLabel == "loggedUser"
    }
    
    // and so on...

What we have to do is prepare browser instance (in our case Firefox one) to click through our tests. We could to it in setup() method:

class ExampleUITest extends GebSpec {
 
    def setup() {
        driver = new FirefoxDriver()
    }
 
    def "Should test feature 1"() {
        // ...
    } 
 
    def cleanup() {
        driver.quit()
    }

This approach works but it has one, big drawback. We all know that UI tests tend to last quite long and creating new browser instance for each, yes, each test method will only make this situation worse as it also takes some time to start browser on your testing server.

Second approach

We also could reuse same browser in each specification (each Geb class) by using setupSpec() and cleanupSpec() methods instead. This will reduce number of new instances created but still we will have many of them, especially in large codebase with many test classes.

Solution

My solution to this issue takes from both approaches presented above. But instead of creating browser for each specification, I am reusing one created in the first executed class.

To make it work we need to introduce common abstract class for all our UI tests:

class IntelliGebSpec extends GebSpec {
 
    static def cachedDriver // static variable will store our single driver instance
 
    def setupSpec() {
        if ( cachedDriver == null) { // in first Specification this will be true
            cachedDriver = new FirefoxDriver()  // so let's create driver and put it in cachedDriver variable
        }
    }
 
    def setup() {
        driver = cachedDriver   // each test should use our cached browser instance
    }
 
    // as we are reusing browser, we should logout from our application after
    // each test to have clean browser state on each test run
    def cleanup() { 
        if ($(id: "logout").isDisplayed()) {
            $(id: "logout").click()
            waitFor { $(id: "inputName").isDisplayed() }
        }
        driver.manage().deleteAllCookies()
    }
}

Summary

In this post I have shown my home made solution to reusing browser in multiple tests. I strongly suggest all of you to check and try Geb, as after over a year of using Selenium I am really impressed by this library. Easy to use with really cool Page Objects.




Published at DZone with permission of Tomasz Dziurko, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)