The Curious Dev

Various programming sidetracks and shiny-object detours

Geb Is Great!

Geb is a Groovy-based layer of magic over the top of Selenium/WebDriver for web-based automation tasks and is a tool worthy of being added to your programming tool belt.

What’s So Special About Geb?

Quoting from the Gebish.org site:

It brings together the power of WebDriver, the elegance of jQuery content selection, the robustness of Page Object modelling and the expressiveness of the Groovy language.

The simplicity and elegance of a typical script makes it very easy to get a basic task up an going within minutes, something we can demonstrate right now.

I wont really cover them here, but the jQuery style CSS selectors are very useful for getting right now at the specific html element you want to manipulate.

Getting It

You can download and build recent snapshot here: https://github.com/geb/geb/downloads and then simply run “gradlew.bat build” after extracting, but I’ve had some problems with this way.

Alternatively, it is available via a Groovy Grab here: http://mvnrepository.com/artifact/org.codehaus.geb/geb-core, using:

@Grapes([
    @Grab("org.codehaus.geb:geb-core:0.7.0"),
    @Grab("org.seleniumhq.selenium:selenium-firefox-driver:2.24.1"),
    @Grab("org.seleniumhq.selenium:selenium-support:2.24.1")
)

Let’s Do Something Useful

Every so often I happen across a twitter stream that I’d rather have as an RSS feed to consume from within Google Reader rather than on twitter itself. There’s a little kink in that task in that twitter are seemingly trying to eradicate the use of RSS, but there are still ways of getting a feed.

One way is by going to the idfromuser.org site which will provide the User ID and RSS feed link immediately. This seems like a great little task to get Geb to do automatically.

Here’s a simple Geb script that will:

  • load up the idfromuser.org site
  • type in the desired twitter username
  • click the submit button
def getTwitterId(def username) {
  def result
  Browser.drive {
    go "http://idfromuser.org"

    assert title == "Get twitter id and twitter RSS feed URL from user name - online tool"

    // enter the value into the search field
    $("input", name: "username").value("${username}")

    //click the submit button
    $("form input", 1).click()

    //wait for page result to load
    waitFor { $("article").children().size() > 0 }

    //extract rss feed link and return to calling obj
    result = $("article div", 1).children().find("a").text()
  }

  return result
}

Building on this, we can now create another script to add the RSS feed to Google Reader:

def addFeedToGoogleReader(def feedLink, def username, def passwd) {
  def feedUrl = java.net.URLEncoder.encode(feedLink)
  def googleReaderUrl = "http://fusion.google.com/add?feedurl=${feedUrl}"

  Browser.drive {
    go googleReaderUrl

    //upon going to above url, we'll check the title of the current page...
    waitFor { title == "Add to Google" }

    //click on the "add to google reader" button
    $("b", text: "Add to Google Reader").click()

    //wait for the google reader login page
    waitFor { title == "Google Reader" }

    if ($("form", id: "gaia_loginform")) {
    //login to google reader
      $("input", name: "Email").value(username)
      $("input", name: "Passwd").value(passwd)
      $("input", name: "signIn").click()
    }

   println "All Done"
 }.close()
}

*** Note: if you’ve got Google’s 2-step verification configured, this will put a kink in things.

Putting It Into Action

All we need to do to run the above scripts is throw them into a groovy file with a simple wrapper which constructs the class and takes in the arguments from command line. There are many ways of writing and running a script, this is how I’ve typically been doing it. One day I’ll look into the CLI functionality.

@Grapes([
  @Grab("org.codehaus.geb:geb-core:0.7.0"),
  @Grab("org.seleniumhq.selenium:selenium-firefox-driver:2.24.1"),
  @Grab("org.seleniumhq.selenium:selenium-support:2.24.1")
])
import geb.Browser

def username = args[0]
g = new GetTwitterFeedAndAddToGoogleReader()
def link = g.getTwitterId(username)
println "${username}=${link}"
g.addFeedToGoogleReader(link, args[1], args[2])

class GetTwitterFeedAndAddToGoogleReader {
  //methods as described above
}

Then you simply run the script, providing the twitter username and your google username and password:

groovy TwitterIdGetter.groovy MarsCuriousity <username> <password>

Page Objects

One area that I haven’t discussed which is worthy of another post is Page Objects.

Page Objects allow you to encapsulate specific content in a block of reusable code. The first thing that comes to mind for me is the login screen of many an application.

If you’re testing different parts of an application, the last thing you want is to duplicate effort in having code to provide the login credentials each and every time. Not very DRY.

I’ll likely cover this in a more in depth Geb post in the future.

Other Uses

This is but one use for Geb, but Geb’s simplicity opens it up to making functional testing easier and thus, more likely to get done.

One area I’ll be covering in the future will be Geb combined with Spock for functional testing of various web-based development, something Geb’s creator Luke Daley has talked about.

Code

All code in this post is here.

Comments

Included file 'facebook_like.html' not found in _includes directory