Version 6, last updated by johan.seland at 15 May 20:42 UTC

Highlevel testing with Selenium

It’s surprisingly easy to test your web applications using Selenium. You have to do the following:

  1. Get the Selenium jars and add them to your project (see code below for SBT users)
  2. Write tests using your favorite testing library. In this example we’ll use ScalaTest.

In your tests you want to do the following before running any tests:

  1. Start your web application programmatically
  2. Start the Selenium client programmatically

You can either record tests using the Selenium firefox plugin and export as java code and translate to Scala or just can simply write the tests by hand.

Add the following to your SBT Project definition to grab the jars:

"org.scalatest" % "scalatest" % "1.6.1" % "test->default",
"org.seleniumhq.selenium" % "selenium-java" % "2.21.0" % "test->default",

Now you can create a test class like this:

class AddEventTest extends FunSuite with BeforeAndAfterAll with Logger {

  private var server : Server       = null
  private var selenium : WebDriver  = null
  private val GUI_PORT              = 8080
  private var host                  = "http://localhost:" + GUI_PORT.toString
  

  override def beforeAll() {
    // Setting up the jetty instance which will be running the
    // GUI for the duration of the tests
    server  = new Server(GUI_PORT)
    val context = new WebAppContext()
    context.setServer(server)
    context.setContextPath("/")
    context.setWar("src/main/webapp")
    server.addHandler(context)
    server.start()

    // Setting up the Selenium Client for the duration of the tests
    selenium = new HtmlUnitDriver();
    selenium.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
  }

  override def afterAll() {
    // Close everyhing when done
    selenium.close()
    server.stop()
  }

  // a test to navigate to the list Events page, from there click the 'New Event' link
  // create a new Event entry, and then check that the new Event is on the 
  // list page 
  val listPageURL = host + "/event/listevent"
  val createPage = host + "/event/createevent"
  val listPageTitle = "App: List Events"
  // create random name to help avoid clashes with existing names
  val eventNameText = Random.nextString(8)
  
  test("From the list page add an new event" ) {
    // navigate to our list page
    selenium.get(listPageURL)
    
    // check that we are on the right page
    expect(listPageTitle) {selenium.getTitle}
    
    // check the link to create a new event exists and that it points to the right page
    // note that findElement throws an exception if it cannot find requested item
    var newEventLink: Box[WebElement] = tryo( selenium.findElement(By.linkText("New Event")) )
    assert(newEventLink.map(_.getAttribute("href")).openOr("") == createPage)
    
    // get the html node that contains the list of events
    var eventList: Box[WebElement] = tryo( selenium.findElement(By.id("eventlist")) )
    assert(! eventList.isEmpty )
    
    // get the <td class="eventName">..</td> elements within the list
    // note we've just asserted that eventList is not empty, so OK to use open_!
    var events : scala.collection.mutable.Buffer[WebElement]= 
        eventList.map(_.findElements(By.className("eventName"))).open_!
    
    // make sure none of them contain the new name
    assert(!events.map(_.getText).contains(eventNameText))
   
    // navigate to the new event page
    newEventLink.foreach(_.click)
   
    // locate the name input element
    var eventName: Box[WebElement] = tryo(selenium.findElement(By.id("eventname")))
    assert(!eventName.isEmpty)
    
    // enter the value text of the name and submit
    eventName.foreach(x => {
      x.sendKeys(eventNameText)
      x.submit
    })
    
    // we should now be back at the list page
    expect(listPageTitle) {selenium.getTitle}
    
    var eventList2: Box[WebElement] = tryo( selenium.findElement(By.id("eventlist")) )
    assert(! eventList2.isEmpty )
    
    // get the <td class="eventName">..</td> elements within the list
    // note we've just asserted that eventList is not empty, so OK to use open_!
    var events2 : scala.collection.mutable.Buffer[WebElement]= 
        eventList2.map(_.findElements(By.className("eventName"))).open_!
    
    // now make sure one of them contain the new name
    assert(events2.map(_.getText).contains(eventNameText))
  }

Using specs2

Selenium