Selenium

Playing With Jetty And Selenium

Now that we’ve seen how to get Jetty up and running, let’s integrate it with Selenium. We’ll be using Selenium 2 to check a simple JSP.

So, in addition to the Jetty-related jars mentioned in the earlier post, we will need the following Selenium jars:

selenium-java-[version].jar
selenium-server-standalone-[version].jar

They are available here.

We have a JSP:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h1>From The JSP</h1>

<h2>h2 text</h2>

</body>
</html>

This page is served when one tries to go to http://localhost:8080.

And, we also have a simple test class:

package com.bitmotif.example;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.server.SeleniumServer;

import static org.junit.Assert.assertEquals;

/**
 * User: pjberry
 * Date: 3/22/11
 * Time: 6:29 PM
 */
public class ExampleTest {

    private SeleniumServer seleniumServer;
    private Server applicationServer;
    private WebDriver driver;

    @Before
    public void setUp() throws Exception {
        startApplicationServer();
        startSeleniumServer();
        driver = new FirefoxDriver();
    }

    @After
    public void tearDown() throws Exception {
        driver.quit();
        seleniumServer.stop();
        applicationServer.stop();
    }

    @Test
    public void testPageContents() {
        driver.get("http://localhost:8080");

        WebElement element = driver.findElement(By.tagName("h2"));

        assertEquals("h2 text", element.getText());
    }

    private void startSeleniumServer() throws Exception {
        seleniumServer = new SeleniumServer();
        seleniumServer.start();
    }

    private void startApplicationServer() throws Exception {
        applicationServer = buildServer( buildWebAppContext() );
        applicationServer.start();
    }

    private Server buildServer(WebAppContext webApp) {
        Server server = new Server(8080);
        server.setHandler(webApp);
        return server;
    }

    private WebAppContext buildWebAppContext() {
        WebAppContext webApp = new WebAppContext();
        webApp.setContextPath("/");
        webApp.setResourceBase("./src/main/webapp");
        return webApp;
    }

}

So, what do we have here? Simply, we fire up Jetty, then fire up the Selenium server, and lastly, we fire up the WebDriver (client). With our server running and proxy running, we use our client to load a page. Next, we load a page and get the h2 tag. Then we check the text in the h2 tag.

This is freaking awesome. Basically, we have a way to test against a container without having to do a deployment! Extending this idea, we can then do things like create tests for Javascript without leaving the IDE or automate acceptance tests for continuous integration without a bunch of tedious configuration. That’s pretty powerful stuff.

Selenium Remote Control For Java — A Tutorial (part 4)

One of the really cool things about Selenium Remote Control is that it gives you access to its JavaScript underpinnings using getEval. With this guy we can do something like this:

public void testGetEval()
      throws Exception
   {
      selenium.open(TEST_PAGE_URL);
      //Using some JavaScript available from Selenium
      String childSpanTextSnippet =
         " {" +
            " var tdElem = this.page().findElement('id=theLastCell'); " +
            " var tdChildSpans = tdElem.getElementsByTagName('span'); " +
            " var spanTexts = ''; " +
            " for(var i = 0; i < tdChildSpans.length; i++) { " +
            "  if(i > 0) spanTexts = spanTexts + ', ';   " +
            "  spanTexts = spanTexts + tdChildSpans.item(i).innerHTML; " +
            " }; " +
            "spanTexts" +
            "}";

      String texts = "row two, cell two";
      assertEquals(texts, selenium.getEval(childSpanTextSnippet));
   }

If we place this in the test class we created in a previous tutorial and run it, we should see a green bar. Pretty cool, eh?

So, what’s going on here? Basically, we are using Selenium to execute a snippit of JavaScript. What’s more, in our snippet we can use functions defined in Selenium Core, in this case findElement. The function accepts all the different types of locators to try to find an element in the DOM. After we get the element, we do some processing, and we get the results back in Java land as a String.

We aren’t limited to using what is provided by Selenium. Consider the following:

 public void testGetEval_UsePlainJavaScript()
      throws Exception
   {
      selenium.open(TEST_PAGE_URL);

      String firstTitleSnippet =
            "{" +
            " var bodyElem = document.getElementsByTagName('title')[0]; " +
            " bodyElem.innerHTML; " +
            "}";

      assertEquals("Selenium Functional Test Runner", selenium.getEval(firstTitleSnippet));
   }

By using a snippet of JavaScript, we actually have access to the DOM of the test runner. Once again, pretty cool. With getEval we have a simple yet powerful way to extend Selenium’s functionality.

Selenium Remote Control For Java — A Tutorial (part 3)

Let’s take a look at working with popup windows and Selenium Remote Control.

The simplest way to work with popups is to do whatever creates the popup (in this case, clicking a link) and then use the getAllWindowNames() and selectWindow(String windowId) methods. The following method (placed in our test class created in part 2) demonstrates creating and identifying popups:

(Note that the example code refers to a real page.)

 public void testPopUpCreation()
      throws Exception
   {
      selenium.open(TEST_PAGE_URL);
      String[] windowNames = selenium.getAllWindowNames();

      assertEquals(1, windowNames.length);
      assertEquals("myiframe", windowNames[0]);

      selenium.click("link=This link opens a popup");
      selenium.waitForPopUp("popup", MAX_WAIT_TIME_IN_MS);
      windowNames = selenium.getAllWindowNames();

      assertEquals(2, windowNames.length);
      assertTrue(Arrays.asList(windowNames).contains("myiframe"));
      assertTrue(Arrays.asList(windowNames).contains("popup"));
   }

So, we find all the windows Selenium knows about. In this case we end up with two windows: the main window, “myiframe” and the popup, “popup”.

Let’s use this information to actually interact with the popup.

public void testWindowSelection()
      throws Exception
   {
      selenium.open(TEST_PAGE_URL);
      assertEquals(TEST_PAGE_TITLE, selenium.getTitle());

      selenium.click("link=This link opens a popup");
      selenium.waitForPopUp("popup", MAX_WAIT_TIME_IN_MS);
      selenium.selectWindow("popup");

      assertEquals("Bit Motif", selenium.getTitle());
   }

We create the popup, and then use selectWindow to let Selenium know this is the window we are working with. In this case, we just get the title of the page. But, at this point, we could do all the things we’d normally do.

After we’ve finished with the popup, we probably want to close it, and go back to originating window. Doing this is, well, a little ugly. But, it works. Here’s the code:

   public void testWindowSelection_ClosePopUp_ReturnToMainWindow()
      throws Exception
   {
      selenium.open(TEST_PAGE_URL);
      assertEquals(TEST_PAGE_TITLE, selenium.getTitle());

      selenium.click("link=This link opens a popup");
      selenium.waitForPopUp("popup", MAX_WAIT_TIME_IN_MS);
      selenium.selectWindow("popup");

      assertEquals("Bit Motif", selenium.getTitle());

      // close popup
      selenium.close();

      // select original window
      selenium.selectWindow(null);

      assertEquals(TEST_PAGE_TITLE, selenium.getTitle());
   }

Most of the above we’ve seen before. We open the popup, point Selenium to it, and check something. What’s new is the close method. It does what you’d expect a method named close to do.

After the popup is closed, we have to tell Selenium to look at another window. (If we don’t, when we try to do something, we get an exception.) In our case, we want to work work with the “main” window. To do this, we have to pass null to selectWindow.

It’s a bit counterintuitive. You might think that it would be “myiframe” or something like that, but no. Once we have the main window, we can process as usual.

One final note on working with popups. Prior to Selenium Remote Control verison 0.9.1, I couldn’t get popups working with *iehta browser launcher. So, make certain you have a recent version of Selenium Remote Control. The jars used in this example can be found here.

Get poppin!

Selenium Remote Control For Java — A Tutorial (part 2)

In order to test a system, we need to be able to interact with it and make assertions about it. When the system we wish to test is a web application UI, we need to be able to interact with the page/browser and making assertions about the same. Let’s look at how we can this with Selenium Remote Control and JUnit.

The most common interactions are accomplished through the following methods in DefaultSelenium:

  • open(String url)
  • click(String locator)
  • type(String locator, String value)
  • select(String locator, String optionLocator)
  • check(String locator)
  • waitForPageToLoad(String timeoutInMilliseconds)

Now that we have a way of interacting, we need to be able to get information about a page. DefaultSelenium has many methods for getting information about a page. The ones that I use the most are:

  • getTitle()
  • getText(String locator)
  • getValue(String locator)
  • isEditable(String locator)
  • isElementPresent(String locator)
  • getSelectedLabel(String locator)
  • getSelectedValue(String locator)
  • isSomethingSelected(String locator)
  • isChecked(String locator)
  • getAlert()

Rather than trying to describe all of the methods above (that’s what the JavaDoc is for), lets look at some code.

Getting Started
First, let’s create the test class with the set up, tear down, and constants we’ll need. (Note that the example code refers to a real page.)

public class TestPageForSeleniumRemoteControlTest
   extends TestCase
{
   private static final String MAX_WAIT_TIME_IN_MS = "60000";
   private static final String BASE_URL = "http://www.bitmotif.com";
   private static final String TEST_PAGE_URL =
      BASE_URL + "/test-page-for-selenium-remote-control";
   private static final String TEST_PAGE_TITLE =
      "Bit Motif » Test Page For Selenium Remote Control";

   private Selenium selenium = new DefaultSelenium( "localhost",
                                                    4444,
                                                    "*firefox",
                                                    BASE_URL);
   private SeleniumServer seleniumServer;

   public void setUp()
      throws Exception
   {
      seleniumServer = new SeleniumServer();
      seleniumServer.start();
      selenium.start();
   }

   public void tearDown()
      throws Exception
   {
      selenium.stop();
      seleniumServer.stop();
   }
}

Checking the Title
Now, let’s open a page and check the title.

public void test_NavigatingPages_WithoutClickingLink()
   throws Exception
{
   selenium.open(BASE_URL);
   selenium.open(TEST_PAGE_URL);
   assertEquals(TEST_PAGE_TITLE, selenium.getTitle());
}

Navigating
Next, let’s test clicking a link that takes us to a new page. We need to use waitForPageToLoad. If we don’t, funny things can happen. For example, we could ask for information before the page is loaded. It wouldn’t be there and the test would fail.

public void test_NavigatingPages_ClickingLink()
   throws Exception
{
   selenium.open(BASE_URL);

   selenium.click("link=Test Page For Selenium Remote Control");
   selenium.waitForPageToLoad(MAX_WAIT_TIME_IN_MS);

   assertEquals(TEST_PAGE_TITLE, selenium.getTitle());
}

Verifying an Element Exists
If we want to check that an element exists, we can do the following:

public void testIsElementPresent()
   throws Exception
{
   selenium.open(TEST_PAGE_URL);

   assertTrue(selenium.isElementPresent("id=textInput"));
}

Text Inputs
Let’s type something in a text box. Notice that we use the getValue to check what is in the text input.

public void testEnterValuesIntoTextField_CheckWithGetValue()
   throws Exception
{
   selenium.open(TEST_PAGE_URL);
   assertEquals("", selenium.getValue("id=textInput"));

   selenium.type("id=textInput", "Text In The Field");

   assertEquals("Text In The Field", selenium.getValue("id=textInput"));
}

What happens when we use getText to check what we typed? In this case, the text we are interested in is actually the value of the input. Since the input element does does not have any text, the getText method returns an empty string.

 public void testEnterValuesIntoTextField_CheckWithGetText()
    throws Exception
{
    selenium.open(TEST_PAGE_URL);
    assertEquals("", selenium.getText("id=textInput"));

    selenium.type("id=textInput", "Text In The Field");

    assertEquals("", selenium.getText("id=textInput"));
}

Checkboxes
Let’s click a checkbox:

public void testClickingACheckBox_UseCheckAndIsCheckedMethods()
   throws Exception
{
   selenium.open(TEST_PAGE_URL);
   assertFalse(selenium.isChecked("id=checkBoxInput"));

   selenium.check("id=checkBoxInput");

   assertTrue(selenium.isChecked("id=checkBoxInput"));
}

Now, let’s look at clicking a checkbox and checking its value a different way — let’s use click and getValue.

public void testCheckingACheckBox_UseClickAndGetValueMethods()
   throws Exception
{
   selenium.open(TEST_PAGE_URL);
   assertEquals("off", selenium.getValue("id=checkBoxInput"));

   selenium.click("id=checkBoxInput");

   assertEquals("on", selenium.getValue("id=checkBoxInput"));
}

Radio Buttons
When working with radio buttons, the form of the locator is a little different. In the locator, we give both the name (input name) and value (value of the radio button).

public void testClickingARadioButton_UseCheckAndIsCheckedMethods()
   throws Exception
{
   selenium.open(TEST_PAGE_URL);

   assertFalse(selenium.isChecked("name=radioButton value=a"));
   assertFalse(selenium.isChecked("name=radioButton value=b"));

   selenium.check("name=radioButton value=b");

   assertTrue(selenium.isChecked("name=radioButton value=b"));
   assertFalse(selenium.isChecked("name=radioButton value=a"));
}

We could also use click and getValue when working with radio buttons. But, it gets a little hard to work with. We can’t just ask for the value of the input. And, the individual buttons have a value of “off” or “on”. Consider:

public void testClickingARadioButton_UseClickAndGetValueMethods()
   throws Exception
{
   selenium.open(TEST_PAGE_URL);
   assertEquals("off", selenium.getValue("name=radioButton"));
   assertEquals("off", selenium.getValue("name=radioButton value=a"));
   assertEquals("off", selenium.getValue("name=radioButton value=b"));

   selenium.click("name=radioButton value=b");

   assertEquals("off", selenium.getValue("name=radioButton"));
   assertEquals("off", selenium.getValue("name=radioButton value=a"));
   assertEquals("on", selenium.getValue("name=radioButton value=b"));
}

Selects
Selects can be a little more complex than your average input. First, there is the select itself we must identify. Then, there are the options in the select. The options in a select may be identified with ids and values, just the visible text in the option, or some combination thereof. So, we have to use a locator for the select itself and a locator for for the option(s) we are interested in. The locator of the option(s) can be the option element’s id, value, label, or index in the select.

Once something is selected, we can use getValue, getSelectedValue, and getSelectedLabel.

public void testSelectFromDropDown_NoValuesInSelect_UseLabelOptionLocator()
   throws Exception
{
   selenium.open(TEST_PAGE_URL);
   assertEquals("option one", selenium.getSelectedLabel("id=selectWithLabelsOnly"));
   assertEquals("option one", selenium.getValue("id=selectWithLabelsOnly"));

   selenium.select("id=selectWithLabelsOnly", "label=option two");

   assertTrue(selenium.isSomethingSelected("id=selectWithLabelsOnly"));
   assertEquals("option two", selenium.getSelectedLabel("id=selectWithLabelsOnly"));
   assertEquals("option two", selenium.getValue("id=selectWithLabelsOnly"));
}

Lets look at the same test but using the index verison of the select locator.

public void testSelectFromDropDown_NoValuesInSelect_UseIndexOptionLocator()
   throws Exception
{
   selenium.open(TEST_PAGE_URL);
   assertEquals("option one", selenium.getSelectedLabel("id=selectWithLabelsOnly"));
   assertEquals("option one", selenium.getValue("id=selectWithLabelsOnly"));

   selenium.select("id=selectWithLabelsOnly", "index=1");

   assertTrue(selenium.isSomethingSelected("id=selectWithLabelsOnly"));
   assertEquals("option two", selenium.getSelectedLabel("id=selectWithLabelsOnly"));
   assertEquals("option two", selenium.getValue("id=selectWithLabelsOnly"));
}

Notice what we get if we look at a select with values.

public void testSelectFromDropDown_LabelsAndValuesInSelect_UseLabelLocator()
   throws Exception
{
   selenium.open(TEST_PAGE_URL);
   assertTrue(selenium.isSomethingSelected("id=selectWithLabelsAndValues"));

   String selectedLabel = selenium.getSelectedLabel("id=selectWithLabelsAndValues");
   assertEquals("option one", selectedLabel);
   assertEquals("1", selenium.getValue("id=selectWithLabelsAndValues"));
   assertEquals("1", selenium.getSelectedValue("id=selectWithLabelsAndValues"));

   selenium.select("id=selectWithLabelsAndValues", "label=option two");

   assertTrue(selenium.isSomethingSelected("id=selectWithLabelsAndValues"));

   selectedLabel = selenium.getSelectedLabel("id=selectWithLabelsAndValues");
   assertEquals("option two", selectedLabel);
   assertEquals("2", selenium.getValue("id=selectWithLabelsAndValues"));
   assertEquals("2", selenium.getSelectedValue("id=selectWithLabelsAndValues"));
}

Alert Boxes
Often we need to work with alert boxes. The getAlert method is the man. Invoking this method is the same as clicking “OK” on the alert box. It also returns the text in the alert box.

public void testAlertBox()
   throws Exception
{
   selenium.open(TEST_PAGE_URL);
   selenium.click("id=popUpDiv");
   assertEquals("You clicked the div.", selenium.getAlert());
}

Conclusion
With Selenium and JUnit, we can easily test web UIs. The examples here are basic, but they demonstrate how just a few basic Selenium commands can get you most of what you need to test the UI.

Selenium Remote Control For Java — A Tutorial

The coolest element nowadays is Selenium. You can even control it remotely.

What is Selenium?
Selenium is a testing tool for web applications that uses JavaScript and Iframes to run tests directly in a browser. There are several test tools based on this technology: Selenium Core, Selenium IDE, Selenium Remote Control, and Selenium on Rails.

The aforementioned Selenium Remote Control has become the tool I reach for when testing web applications. In fact, it is so useful that I hardly use HttpUnit any more.

What is Selenium Remote Control?
It is the remote control for Selenium. Duh. Ok, it really is that. A better, less obnoxious description is that Selenium Remote Control is a tool that allows us to test against the browser using our programming language of choice (in this case, Java).

How does Selenium Remote Control Work?
Selenium Remote Control depends on a server called—what else?—Selenium Server. The Selenium Server is capable of manipulating supported browsers and acts as a client-configured proxy between a browser and a website. This allows it to run JavaScript against a site.

How do I use Selenium Remote Control?
First, we’ll need to get the jars. With the jars, we’ll get the server and the client we’ll use for testing. (For this tutorial, the selenium-remote-control-0.9.1-SNAPSHOT nightly was used.) In the folder structure of the download, there are two jars that we want: selenium-server.jar in the “server” folder and selenium-java-client-driver.jar in the “java” folder.

We need to be able to start and stop the Selenium Server. We can do this at the command line:

Start:

java -jar selenium-server.jar

Stop:


http://localhost:4444/selenium-server/driver/?cmd=shutDown

To limit configuration and external dependencies, we can do this in our test code using the SeleniumServer class:

SeleniumServer server = new SeleniumServer();
server.start();
...
server.stop();

With the server running, we may now use a client:

Selenium selenium = new DefaultSelenium( String seleniumServerHost,
                                         int seleniumServerPort,
                                         String browserType,
                                         String baseURL);
selenium.open("http://www.somesite.com/somePage.html");
selenium.stop();

An explanation of the variables in the DefaultSelenium constructor:

  • seleniumServerHost is the where the Selenium Server is running. Typically, it is localhost.
  • seleniumServerPort is the port on which the Selenium Server is listening. The default is 4444.
  • browserType is the type of browser you want to use for testing. Common browser types are *firefox, *iexplore, *opera.
  • baseURL is the base URL for the site you are testing. To adhere to the Same Origin Policy , the Selenium object created is tied to that particular URL and can only be used for that URL.

Now, just opening a page isn’t all that useful. We need to interact with the page. To do this, we use our selenium client’s methods with locators. For example:

selnium.click("link=Text For Some Link");

The string “link=Text For Some Link” is a locator. Most of operations involve locators that tie a Selenium command to elements in an HTML document.

Locators take the form of

“locatorType=argument”

A locator type can be an element id, an element name, an xpath expression, link text, and more.

A few examples:

selenium.click(“id=idOfThing”);                           //an id locator
selenium.click(“name=nameOfThing”);                       //a name locator
selenium.click(“xpath=//img[@alt='The image alt text']”); //an xpath locator
selenium.click(“dom=document.images[56]” );               //a DOM locator
selenium.click(“link=Test Page For Selenium”);            //a link locator
selenium.click(“css=span#firstChild”);                    //a css locator

Of course, there is more to Selenium than just clicking. But, the above gives you an idea of the types of locators, and how they are typically used with a method on the selenium object. We’ll explore other actions (methods) and locator types later.

The last step is to integrate the interaction and checking in a test. In this case, we’ll use JUnit to check the results of clicking a link. Note that the code below actually refers to a real link and page.

package com.bitmotif.seleniumexamples;

import com.thoughtworks.selenium.Selenium;
import com.thoughtworks.selenium.DefaultSelenium;
import junit.framework.TestCase;
import org.openqa.selenium.server.SeleniumServer;

public class ExampleTest
   extends TestCase
{
   private static final String MAX_WAIT_TIME_IN_MS = "60000";
   private static final String BASE_URL = "http://www.bitmotif.com";
   private Selenium selenium = new DefaultSelenium( "localhost",
                                                    4444,
                                                    "*firefox",
                                                    BASE_URL);
   private SeleniumServer seleniumServer;
   public void setUp()
      throws Exception
   {
      seleniumServer = new SeleniumServer();
      seleniumServer.start();
      selenium.start();
   }

   public void tearDown()
      throws Exception
   {
      selenium.stop();
      seleniumServer.stop();
   }

   public void testClickingLink()
      throws Exception
   {
      selenium.open(BASE_URL);
      selenium.click("link=Test Page For Selenium Remote Control");
      selenium.waitForPageToLoad(MAX_WAIT_TIME_IN_MS);

      String expectedTitle = "Bit Motif » Test Page For Selenium Remote Control";
      assertEquals(expectedTitle, selenium.getTitle());
   }
}

The only thing new in the code above is the waitForPageToLoad method. Sometimes an action such as clicking a link or submitting a form results in a page load. In order to make sure the new page is loaded before we attempt to do anything else, we use this method.

With that, we now have an example of using Selenium Remote Control as part of a test.