Friday, 1 of August of 2014

Testing With Selenium 2

With Selenium 2 you can test your web application. The test code basically requires 4 steps:

  • Creates a browser object
  • Sends it to a URL
  • Manipulates UI elements
  • Screen scrapes to verify correct results

Its easy, although the screen scraping can be (not surprisingly) a little fragile.

I have used Selenium 2 to construct end-to-end tests for the Geo Portal. The portal is a search tool for an institution’s repository of geographic information. The repository holds many thousand layers so the portal must provide appropriate, well-ranked search results.

When using Selenium 2, you must first create a web browser object and send it to the portal page we want to test:

WebDriver webDriver = new FirefoxDriver();
webDriver.get("http://geoportal-demo.atech.tufts.edu");

With the browser object in place, the first two steps are complete. The only things left to do are manipulate UI elements and screen scrape.

For every search the portal executes it, like Google, displays the number of results where each result is a geographic data layer. These total number of results are displayed in a SPAN element. Since my tests often rely on the number of layers found, I wrote a function to screen scrape and return the search result count. The code simply gets the relevant DOM element by its ID, obtains the text and strips of the “(” and “)” characters that surround the number.

public static int getSearchResultsCount(WebDriver webDriver)
{
WebElement spanElement = webDriver.findElement(By.id("resultsNumber"));
String text = spanElement.getText();
String temp = text.replace("(", "");
temp = temp.replace(")", "");
int layerCount = Integer.parseInt(temp);
return layerCount;
}

The portal supports geo-coding. That is, there is a text field for the user to enter an address or a place name. If a location is entered, the application uses Google to obtain geodetic coordinates for the place and uses the type of place to determine the zoom level. Then, the map is updated and a search for geographic data centered on the new map is performed and the results are displayed.

An easy way to grossly test this functionality is to zoom the map all the way out and note how many layers the search returned. Then, enter a location to zoom in on a region and note how many layers the search returned. Since we zoomed in to a small region, many layers should have been considered not relevant and filtered out of the result set. Therefore, the number of search results should have decreased if the geo-coding worked. Here’s the code that performs the geo-coding test:

private static void geoCodingTest(WebDriver webDriver)
{
logger.info(" in geoCodingTest");
zoomToWorld(webDriver);
pause();
int startResultsCount = getSearchResultsCount(webDriver);
setLocation(webDriver, "Boston, MA");
pause();
int endResultsCount = getSearchResultsCount(webDriver);
assertTrue("geoCoding test failed", startResultsCount > endResultsCount);
}

The function zoomToWorld simply clicks the UI button to zoom the map all the way out. The function pause sleeps for a second. This is important because the operation like zooming the map to view the entire world is not instantaneous. Map tiles and search results must be obtained via AJAX and displayed. Finally, JUnit’s assert it used to check the observed results.

Entering text into a UI element is very simple:

private static void setField(WebDriver webDriver, String fieldId, String value)
{
WebElement field = webDriver.findElement(By.id(fieldId));
field.clear();
field.sendKeys(value);
}

Note that the main test function is trivial. This means you can quickly develop many tests. Then, whenever the application changes one can simply run the tests to see if anything might have unexpectedly broken. This is especially if your modifying code you did not write or wrote a while ago. Instead of haphazardly testing an application you’re not intimately familiar with and hoping for the best you can run a real test suite and have confidence the application works.