Selenium Remote Control (RC), part of a suite of tools from the Selenium project, is an automated test framework for web applications. Selenium RC supports many programming languages and almost all browsers. The most important advantage of Selenium RC is the method in which the browser is driven. Unlike other web UI automation tools, Selenium RC drives the browser by JavaScript, so tests will not be interrupted by mouse events. Testers can do other tasks while the tests run.
Selenium Grid extends Selenium RC by running tests on different servers in parallel. It reduces the time, and subsequently the cost, for testing in various browsers under multiple operation systems.
Selenium tool suites are open source projects with limited formal documentation and guidance, so the learning curve might be steep. In this article, learn about testing with Selenium Grid (Version 1.0.6), programming in Java, and running with the TestNG testing framework.
Selenium Grid has two components: Selenium Hub and Remote Control. The hub receives requests from tests (the same as Selenium RC), and then allocates remote controls that are registered to the hub to each test, as shown in Figure 1:
Figure 1. Relationship of Selenium Hub and Selenium RC in Selenium Grid
Testers can run tests without code changes in Selenium Grid. The whole process is transparent; testers do not need to know or care about the actual infrastructure.
If you're familiar with Selenium RC, you'll be able to easily run tests with Selenium Grid. You can also run existing code in parallel on multiple machines, which saves test execution time and quickly yields feedback of test results. However, Selenium Grid itself does not provide a parallel running strategy. If you want to take advantage of Selenium Grid, you need to write your selenium tests in parallel mode.
Preparing to use Selenium Grid
To get started with Selenium Grid, you first need to download and install it (see Resources for a link). Selenium Grid is a folder containing library JAR files, example files, Ant's build file, and other files. To run tests in Selenium Grid, you will need:
- Ant, Version 1.7 or later, which is used for compiling, assembling, testing, and running Java applications (described in the build files as target and extension points).
- JDK 5+.
- Basic knowledge of Selenium RC, since Selenium Grid is based on Selenium RC. (See Resources for information about Selenium RC). Testers should know how to write and run tests using Selenium RC.
The example in this article uses Java technology and TestNG as the programming language and test framework. TestNG is designed to simplify a broad range of testing needs and to extend the JUnit. (See Resources for more information about TestNG.)A simple TestNG configure file is shown in Listing 1.
Listing 1. Simple TestNG configure file
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite1" parallel="methods" thread-count="2">
<test name="Testcase20" >
<classes>
<class name="com.test.workflow.device.testcase20"/>
</classes>
</test>
</suite>
|
The <suite> tag can represent one TestNG
XML file containing one or more tests. The
<test> tag allows a test to contain one
or more TestNG classes. The <class> tag
signifies that a TestNG class can contain one or more test methods. (See
Resources for more detailed information about
tags.) The test method is defined in Java files, as shown in Listing 2:
Listing 2. Test method defined in Java file
@Test
public void testMethod()
{
....
}
|
Testers use the Java programming language and testing framework to write test scripts, and run TestNG classes from the command line using Ant. Let's take a look at the whole process of running TestNG using Ant.
- Run
ant(target name) [build file name]in command line. - Ant reads build.xml file to get project parameters, import files, classpath definition, target definition, and so on.
- Ant complies the Java source code to TestNG classes.
- Ant focuseson the target to run and gets the target configuration.
- Read TestNG configure file to get parameters, test classes name, and so on.
- Run TestNG classes as configured in TestNG configure file.
This article focuses on how to run tests in parallel using Selenium Grid integrated with TestNG and Ant, so we'll use a simple application based on a PHP page. The test case is designed to simply click the tabs on the page. Figure 2 shows the example application web page.
Figure 2. Part of application web page
Listing 3 provides the example source code for the tabs.
Listing 3. Source code for tabs
<div class="Tabs" style="width: 100%;"> <a class="Current">Test Case</a> <a>View Time</a> <a>Run Scripts</a> <a>Long Run</a> <a>LA</a> <a>s-CAT</a> <a>Jmeter</a> </div> |
The test machines were prepared as follows.
| IP | OS Type |
|---|---|
| 9.181.138.75 | win2003 |
| 9.181.138.186 | win2003 |
| 9.181.128.184 | Linux |
Put the test folder, whose content is shown in Figure 3, in the selenium-grid-1.0.6 directory.
Figure 3. Test case folder content
The src directory contains the Java source code files. The target directory contains all class files, after compilation, and report files. The build.xml file, shown in Listing 4, is an Ant build file that defines the target configuration. It includes which TestNG configure file to call, project parameters, the lib file path, and so on. The testng.xml file is the TestNG configuration file for the example test case.
Listing 4. build.xml
<project name="Selenium Grid Test" default="run" basedir=".">
<description>Selenium Grid Test</description>
<property name="rootdir" value="${basedir}/.."/>
<property file="${rootdir}/project.properties"/>
<property name="name" value="Selenium Grid Demo"/>
<property name="artifact" value="selenium-grid-demo"/>
<property name="version" value="SNAPSHOT"/>
<property name="selenium.version" value="SET ME"/>
<property name="build.src" location="src"/>
<import file="${rootdir}/lib/build/common-build.xml" />
<path id="compile.classpath">
<fileset dir="${rootdir}/vendor">
<include name="selenium-java-client-driver-${selenium.version}.jar"/>
<include name="testng-5.7-jdk15.jar"/>
<include name="commons-logging-1.0.4.jar"/>
</fileset>
<pathelement location="${rootdir}/tools/target/classes"/>
<pathelement location=
"${rootdir}/tools/target/dist/lib/selenium-grid-tools-standalone-${version}.jar"/>
<pathelement location="${rootdir}/lib/selenium-grid-tools-standalone-${version}.jar"/>
<pathelement path="${java.class.path}/"/>
</path>
<path id="runtime.classpath">
<path refid="compile.classpath"/>
<pathelement path="${build.output}/"/>
</path>
<target name="run" depends="compile" description="test">
<java classpathref="runtime.classpath"
classname="org.testng.TestNG"
failonerror="true">
<sysproperty key="java.security.policy" file="${rootdir}/lib/testng.policy"/>
<arg value="-d" />
<arg value="${basedir}/target/reports" />
<arg value="-suitename" />
<arg value="suite1" />
<arg value="testng.xml"/>
</java>
</target>
<target name="build" depends="compile"/>
<target name="dist" depends="build"/>
<target name="coverage-analysis" />
</project>
|
Now that the environment and test data are set up, you can run three different scenarios of parallel testing:
- Same test cases run in different browsers on a server
- Different test cases run in parallel on different servers in different browsers
- Different test cases run in parallel on different servers with same browser
Run same cases in different browsers on a server
To run the same test cases in different browsers on a server, go to the Selenium Grid distribution directory:
ant launch-hub |
In a new window on the same machine, or on another machine, enter either:
ant launch-remote-control ant Denvironment=*iehta launch-remote-control |
or
ant -Dhost=9.181.138.186 DhubURL=http://9.181.138.75:4444 launch-remote-control
ant -Dhost=9.181.138.186 DhubURL=http://9.181.138.75:4444
-Denvironment=*iehta launch-remote-control
|
In a browser, go back to the Hub's console at http://localhost:4444/console. Now you should have two remote controls listed as available, similar to Figure 5.
Figure 4. Selenium Grid Hub console
Put the test class source code from Listing 5 in the src directory.
Listing 5. Test case Java source code
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;
import org.testng.annotations.Parameters;
public class GridTest2 {
String url = "http://9.181.138.186/index.php";
private Selenium selenium= null;
@Parameters({ "bs" })
@BeforeClass
public void startBroswer(String broswer)
{
selenium= new DefaultSelenium("localhost", 4444, broswer, url);
selenium.start();
selenium.open(url);
selenium.windowMaximize();
}
@Test
public void test() throws InterruptedException
{
selenium.click("xpath=//a[contains(text(),\'LA\')]");
Thread.sleep(10000);
}
@AfterClass
public void clear() {
selenium.stop();
}
}
|
Change the content of the testng.xml, as shown in Listing 6:
Listing 6. TestNG configure file content
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="suite1" verbose="1" annotations="JDK" parallel="tests" thread-count="2">
<test name="test1">
<parameter name="bs" value="*firefox"/>
<classes>
<class name="GridTest2" />
</classes>
</test>
<test name="test2">
<parameter name="bs" value="*iehta"/>
<classes>
<class name="GridTest2" />
</classes>
</test>
</suite>
|
The bs parameter in the testng.xml file defines
that test1 runs in the Firefox browser and test2 runs in Internet
Explorer. The parallel attribute defines that
the tests run in parallel. The thread-count
attribute defines the count of threads to run. There are only two tests
defined, so the two tests will run at the same time.
Open a window, and go to the test directory:
ant run |
The test case will run automatically.
Different cases run in parallel on different servers in different browsers
To run different test cases in parallel on different servers on different browsers, go to the Selenium Grid distribution directory:
ant launch-hub |
In a new window on the same machine, or in a window on another machine, enter:
ant launch-remote-control ant Dport=6666 Denvironment=*iehta launch-remote-control |
In a window on machine 9.181.138.186, enter:
ant -Dhost=9.181.138.186 DhubURL=http://9.181.138.75:4444 launch-remote-control |
In a window on machine 9.181.138.184, enter:
ant -Dhost=9.181.138.184 DhubURL=http://9.181.138.75:4444 launch-remote-control |
In a browser, go back to the Hub's console at http://localhost:4444/console. You should now have four remote controls listed as available. It should look similar to Figure 5.
Figure 5. Selenium Grid Hub console
Put the test class source code in Listing 7 in the src directory.
Listing 7. Test case Java source code
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;
public class GridTest2(3/4) {
String url = "http://9.181.138.186/index.php";
private Selenium selenium= null;
@Parameters({ "bs" })
@BeforeClass
public void startBroswer()
{
selenium= new DefaultSelenium("localhost", 4444, broswer, url);
selenium.start();
selenium.open(url);
selenium.windowMaximize();
}
@Test
public void test() throws InterruptedException
{
selenium.click("xpath=//a[contains(text(),\'View Time\')]");
//any code is ok
Thread.sleep(10000);
}
@AfterClass
public void clear() {
selenium.stop();
}
}
|
Change the contents of the testng.xml file, as shown in Listing 8:
Listing 8. TestNG configure file content
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="suite1" verbose="1" annotations="JDK" parallel="tests" thread-count="2" >
<test name="test2" junit="false" >
<parameter name="bs" value="*iehta"/>
<classes>
<class name="GridTest2" />
</classes>
</test>
<test name="test3" junit="false">
<parameter name="bs" value="*firefox"/>
<classes>
<class name="GridTest3" />
</classes>
</test>
<test name="test4" junit="false">
<parameter name="bs" value="*firefox"/>
<classes>
<class name="GridTest4" />
</classes>
</test>
</suite>
|
Only two test cases will run at the same time because there are only two threads defined. Though there are four remote controls, the hub will choose RC1 to run GridTest2 and any of two remaining remote controls to run GridTest3 and GridTest4. The parallel running of two tests is random. Figure 6 shows the running status of the hub.
Figure 6. Selenium Grid Hub console
If you want to run all three of these tests at one time, just change
thread-count to 3.
Different methods run in parallel on different servers with same browser
To run different test cases in parallel on different servers in the same browser, go to the Selenium Grid distribution directory:
ant launch-hub |
Open a window on machine 9.181.138.186, and enter:
ant -Dhost=9.181.138.186 DhubURL=http://9.181.138.75:4444 launch-remote-control |
In a window on machine 9.181.138.184, enter:
ant -Dhost=9.181.138.184 DhubURL=http://9.181.138.75:4444 launch-remote-control |
In a browser, go back to the Hub's console at http://localhost:4444/console. Now you should have three or four remote controls listed as available. Put the test class source code from Listing 9 in the src directory.
Listing 9. Test case Java source code
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;
import static com.thoughtworks.selenium.grid.tools.
ThreadSafeSeleniumSessionStorage.closeSeleniumSession;
import static com.thoughtworks.selenium.grid.tools.
ThreadSafeSeleniumSessionStorage.session;
import static com.thoughtworks.selenium.grid.tools.
ThreadSafeSeleniumSessionStorage.startSeleniumSession;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
public class GridTest {
String url = "http://9.181.138.186/index.php";
private Selenium selenium;
@BeforeMethod(alwaysRun = true)
protected void startSession() {
startSeleniumSession("localhost", 4444, "*firefox", url);
selenium = session();
selenium.open("/");
selenium.windowMaximize();
}
@AfterMethod(alwaysRun = true)
protected void closeSession() {
closeSeleniumSession();
}
@Test
public void test() throws InterruptedException
{
selenium.click("xpath=//a[contains(text(),\'View Time\')]");
Thread.sleep(10000);
}
@Test
public void test2() throws InterruptedException
{
selenium.click("xpath=//a[contains(text(),\'LA\')]");
Thread.sleep(10000);
}
@Test
public void test3() throws InterruptedException
{
selenium.click("xpath=//a[contains(text(),\'Test Case\')]");
Thread.sleep(10000);
}
}
|
Change the contents of the testng.xml file, as shown in Listing 10.
This source code is very different from the common selenium RC scripts. It initializes a Selenium object as a session object, since the methods should be run separately, so Selenium should start the session before the method and close the session after the method.
Listing 10. TestNG configure file content
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="suite1" verbose="1" parallel="methods" thread-count="2">
<test name="test" junit="false">
<classes>
<class name="GridTest" />
</classes>
</test>
</suite>
|
The parallel attribute is changed to
methods, which means that the methods in the
class will run in parallel. The classes will run in sequence.
It's very easy to view the test results. Go to the target folder defined in the build.xml file, and then to the reports folder. Open index.html, and click on the suite name link. You should see the results, as shown in Figure 7 which is the result of the third test sample.
Figure 7. Test results
For more detail, click on the chronological link on the left. You can get detailed information, such as that shown in Figure 8:
Figure 8. Detailed test results
In this article, you have learned how to use Selenium Grid to run Selenium tests in parallel. Doing your automated web application testing with Selenium Grid can save a lot of time and make thrifty use of resources. For example, as described in the second scenario, if a tester has 100 test cases and configures 10 threads to run test cases, it will save 10 times the effort and time. Of course, the number of remote controls is limited.
Parallel testing can also make regression testing more convenient. Hopefully you can take what you've learned in this article and efficiently speed up the testing of your web applications.
Learn
-
SeleniumHQ: Learn all about the
Selenium suite of tools to automate web app testing across many platforms.
-
Selenium and Selenium RC
documentation: This users guide introduces Selenium, teaches its
features, and presents commonly used best practices accumulated from the
Selenium community.
-
Selenium Grid: Read
more about how the Selenium Grid can distribute your tests on multiple
machines so you can run tests in parallel.
-
TestNG: Learn more about
TestNG and how to define the TestNG Ant task.
-
Apache Ant: Read all about the Apache
Ant project.
-
IBM technical events and
webcasts: Stay current with developerWorks' technical events and
webcasts.
Get products and technologies
-
Selenium Grid: Download
Selenium Grid.
-
TestNG: Get TestNG, a
flexible testing framework that can also be used to drive Selenium's
tests.
-
Apache Ant: Get Apache
Ant, a Java library and command-line tool to drive processes described in
build files as targets and extension points dependent upon each
other.
Discuss
-
Selenium
Grid community: Get involved in the Selenium Grid community.
- Create your developerWorks profile today and setup a watchlist on Selenium. Get connected and stay connected
with developerWorks community.
- Find other developerWorks members interested in web development.
-
Join one of our developerWorks groups focused on web topics:
Share what you know.
-
Web 2.0 and middleware: Roland Barcia talks about Web 2.0 and
middleware in his blog.
- Follow developerWorks' members' shared bookmarks on web topics.
- Visit the Web 2.0 Apps forum: Get answers quickly.
- Visit the Ajax forum: Get answers quickly.






