Facebook Twitter Gplus LinkedIn YouTube E-mail RSS
Home Development Using Selenium at GigaSpaces

Using Selenium at GigaSpaces

How we integrated our distributed testing framework with Selenium for automating our Web UI testing

GigaSpaces XAP – as a distributed application platform and data grid – has some unique and interesting testing requirements. I’d like to explain how we use Selenium to test our upcoming web-based administration console in the grid.

Introduction on SGTest testing environment

GigaSpaces Web-UI testing is part of our Service Grid Testing (“SGTest”) project, a distributed testing environment that enables us to emulate how a user would use GigaSpaces features, and allows us to run multiple tests, on multiple machines, and in many different realistic real world scenarios.

To manipulate the grid components – the containers, managers, lookup services, agents, and the rest – we use our Admin API. The Web-UI tests run mainly in our setup, consisting of 1 GSM, 1 GSA, 2 GSCs, and 1 LUS. The tests are configured and managed by the Java TestNG testing framework.

So we have three primary components in our administration UI testing system: the test environment (SGTest), the testing framework (TestNG), and Selenium.

What is Selenium?

Selenium is a testing tool, designed especially for testing web applications. It can interact with an application almost as well as an actual human being can. (In fact, since it doesn’t make any of the silly mistakes humans make, maybe it can interact better.)

UI Testing can be brutal, consisting of long scripts clicking on events in order, hoping no steps are missed. Selenium can help, by programmatically interacting with the application – almost all being done with code of our desired programming language – in this case, Java.

How does it work?

Selenium tests can be executed in two ways.

One is just to run the test case from the Selenium IDE, which is a Firefox add-on seen in the below screen shot on the left hand side. While this is one way to go, in our case it’s not really (at all) what we were looking for. We wanted to be able to integrate the tests into Eclipse, so we can use the features SGTest and TestNG have to offer us, such as the ability to use the Admin API as well as TestNG annotations.

Enter the Selenium RC server. Its job is manage browser instances, and intercept user interface actions from a client, and then execute them on the web application.

Creating a test case

So now we have the pieces in place: Eclipse is our local development application, we’re using Selenium RC to handle the execution of user interaction with our web application, TestNG is the framework we use to start our tests, and SGTest is the environment we’re testing against.

How do we actually create a test? By running an interaction manually, as one option.

The Selenium IDE is able to record interaction with an application. This recording generates code that emulates the recorded interaction. For example, a user clicking on a button called "Submit" will generate the code selenium.click("//button[@id=submit]");, which makes sense if you consider what the code is saying (“act like a user has clicked on a node in the browser DOM with a name of ‘button’ and an id of ‘submit’”).

So, in general writing a test consists of three steps:

    1. Recording the desired test scenario using the Selenium IDE Firefox plug-in.
      This process is essentially executing the test manually; which is done only once, in Firefox.

      selenuim-ide

    2. Copying the generated code to a new Java class.
    3. Manipulating the generated code as we wish from eclipse.

Creating the infrastructure

Our testing infrastructure has 3 parts:

Servers

To view our Web-UI and interact with it, we need to have the web UI actually running (as one might expect.) Therefore, we need to run the gs-webui script manually in the system console. This launches our Web-UI server, which enables the use of the UI.

This means that in order to run tests, we need this server running.
As mentioned before, the Selenium RC server needs to be up as well.

These servers should be launched once, before any test has been executed. After all tests are finished, we want to shut them down.

Libraries

Selenium provides us with a set of jars that we add to our classpath. This is so that Eclipse will recognize Selenium commands. These provide the language-level binding for Selenium RC’s user interactions.

XML

We create two xml files. One called testng.xml; this xml is just our configuration of the TestNG test suite. It defines the suite name, and classes belonging to the suite. We choose to include all of our classes containing tests in the suite, although this is not mandatory.

The second xml file is call test-param.xml; sometimes we want to run the same test a few times, each time with different parameters. This xml file contains all test permutations. By using a special TestNG annotation we can inject these parameters into our test methods.

So, how do we put all of this together? The Selenium jars have a certain inheritance hierarchy; the base class is called SeleniumTestNGHelper. Its main purpose is to provide us with a Selenium object instance, and to launch the browser of our choice where the tests will run. All Selenium commands are visible only via the Selenium instance, so this is essential.

What this means is that tests have to extend this class. But we have a little tweak: instead of having our tests extend SeleniumTestNGHelper, we wrote an abstract class called AbstractSeleniumTest, which handles the issues of making sure the servers are correctly configured and running. All tests now extend this class, which in turn extends SeleniumTestNGHelper.

What is tested? What is not tested?

Our Web-UI is developed with GWT. Selenium recognizes these GWT elements and emulates a user interaction with the application. We test all possible features that appear in the UI (i.e. deployment, statistic viewing, etc.)

The only apparent shortcoming of Selenium is that it is unable to capture OS components, like the file dialog for saving/loading files. Tests of this nature are done manually.

Therefore, we are able to test every interaction with the system that isn’t relying on the OS itself, as file dialogs do. The OS-specific features get tested through normal methods.

Example

Let’s take a look at an example test, step by step. This test undeploys an existing processing unit and asserts that its status has changed to undeployed. It then asserts that it is no longer visible in the UI.

Every test extends AbstractSeleniumTest, as we have explained:

selenium

Next we write a method for starting our desired Grid services. In this case, we use the default configuration (one manager, two containers), and also deploy a processing unit using the Admin API:

selenium2

Now we write our test method. This method is the one generated by the Selenium IDE, as it watches us interact manually with the UI:

selenium3

All Selenium commands have a string as an argument. This argument is called a Locator, and as the name implies, it is used to locate elements in the UI. There are various locating techniques we can use: Xpath, CSS, DOM, etc.; these help us ensure that in case the UI changes, the impact on the test is minimal.

That’s pretty much it. Note how the test uses all 3 participants I mentioned earlier: the SGTest enables use of the Admin API; the TestNG annotations help us control the flow of the test; of course, Selenium does the actual work.

Summary

I am sure you all know the importance of automating tests for your application, whenever such automation is possible; people are much more prone to mistakes than computers are. This cannot be stressed enough.

As you can see, it is fairly easy to write tests with Selenium. The syntax and logic is highly intuitive and I have found working with this tool very satisfying.

There are of course many more capabilities to Selenium not specified here, but hopefully I have given you a pretty good idea on how GigaSpaces uses Selenium to automate our Web-UI testing as much as possible.

Cheers,
Eli

Did you like this? Share it:
 
 Share on Facebook Share on Twitter Share on Reddit Share on LinkedIn
4 Comments  comments 
  • Beef

    I have been heavily automating a webapp with Selenium and had the same issue as you interacting with OS components. I found a workaround, but it is certainly not cross-platform. I selenium up getting as far as the OS component (in my case, a file chooser), then create a simple visual basic for applications script that sends the Tab key to cycle to the dialog window, then sends the filename into the box and hits the open button, then control returns to Selenium. And I run this script from a system call in my Selenium script. If you are using a windows box, this should work, or perhaps running an AutoIT script from a java system call.

    Good luck, email me if you want specific info or my implementation in VBS.

  • Mike

    If you continue using Selenium IDE to generate your tests, you are in for a world of pain when your app gets larger. Any tiny change in the UI will impact many tests.

    Take a look at WebDriver/Selenium 2.0. It has the concept of a Page object that encapsulates a page (as its name implies). Then all tests interact with the page, and the page hides implementation details.

    If you really want to take your testing to the next level, check out Specification by Example by Gojko Adzic

  • elip

    hey guys.
    beef, i know about the workaround you suggested aswell as tools like auto-it. but as you mentioned, it is not cross-platform, so it doesnt really help me much.
    thanks any way though.

    and mike, i read about webdriver and selenium 2.0 and it sounds nice, i will surely consider it. are you using it? how is it serving you?

  • Mike

    I’m not using the webdriver/page aspects of it, but that’s because we started with an earlier version of selenium that didn’t have that concept. I am using the latest beta of selenium 2 so that I don’t have to keep delaying the upgrade of Firefox (I think selenium 1 only supports up to FF 3.5)

    We have our own harness infrastructure (functionally equivalent to page) to isolate our tests from underlying page/navigation flow changes.

© GigaSpaces on Application Scalability | Open Source PaaS and More