-
Notifications
You must be signed in to change notification settings - Fork 5
Home
This project was created to solve a simple problem: 10 web tests run quickly, but 1,000 web tests take too long. To solve this problem, you need a parallel test infrastructure.
##What is parallel-webtest? parallel-webtest is just a JAR, but it provides lots of services for running Selenium 2 aka WebDriver tests. It includes the following features:
- Based on Selenium 2 aka WebDriver
- Configuration is entirely handled via system properties and environment variables. This allows for the use of Maven profiles to easily control the configuration
- Write your test once, and run it locally via a headless Java-based browser (HTMLUnit), a local browser (e.g. Firefox), a single SauceLabs browser, or a suite of SauceLabs browsers.
- Seamless support for cut-and-paste of selenium test code from Selenium IDE into a JUnit test case
- Support for running tests in both local and remote (SauceLabs) environments
- Support for running SauceLabs tests in a highly parallel fashion (e.g. 8 threads running 4 browsers each for 32 concurrent tests)
- Support for standard JDK proxy settings
- Automatic detection and retry for bad SauceLabs initial connections
There is a project checked in to Git called webtest-sample. (URL will go here when published) This is intended to be a tutorial project, and is the best place to get started. For the test to run successfully, you will need to set an environment variable called WEBTEST_HOSTNAME, and install and run SauceLabs Sauce Connect. You can set your hostname, run the test once, and it will emit the command-line that you need to run sauce_connect.
Command-line tool to establish a connection between the GHC network and SauceLabs. Read the GHC-specific documentation on using Sauce Connect.
Firefox extension to record, playback, and debug tests. To use with ghc-webdriver, select Options -> Clipboard Format -> JUnit 4 (WebDriver). The use of the FireBug extension for Firefox is also highly recommended (but not required). Sauce RC / Selenium RC are no longer needed for local testing. If you only test locally with a local browser (HTMLUnit and/or Firefox) and use TeamCity to talk to SauceLabs, you don't need Sauce Connect. Eventually, you may find an issue on SauceLabs (for example, MSIE 7) that you can't easily reproduce locally. For that, you will need to run a single SauceLabs browser and use SauceConnect to debug.
Sauce Connect is a tool that allows bridging the your internal network with SauceLabs. You will need to learn to use Sauce Connect and configure it to run Sauce Labs tests on your local machine.
Subscribe via GitHub.
parallel-webtest makes use of a standard mechanism for setting all options. This allows you to set all of the following options via some combination of environment variables and Java properties. Java properties will override environment variables. This allows you to set global values and then override those values with a particular Maven profile. When you get started working with parallel-webtest (or web testing, for that matter) it's easy to be initially overwhelmed by the possibilities. Here's a checklist to work through:
- What environment[s] do I want to target? My local machine, build agent, shared-dev, shared-qa, some other server[s]?
- What browser configurations do I want to target? e.g. HTMLUnit, local Firefox, single SauceLabs Internet Explorer 7, and the standard corporate suite?
- What do I want my default local build to do?
- What do I want a standard build on my continuous integration build agent to do? Do I want more than one agent configuration (for example, just run a single SauceLabs Internet Explorer 7 on checkin, but run the entire suite once a day?)
Once you work through the list of things that you want, start building profiles in Maven to support what you want to do. By breaking it up into a series of steps (and profiles) you can support any configuration you want - you just need to be clear about what you are trying to accomplish. Make a list (use Excel if you need to) and break it down into a logical series. You can find examples of different configurations in parallel-webtest and webtest-sample. If you have make a coherent list and aren't sure how to make a particular combination work, feel free to ask for help.
WEBTEST_HOSTNAME "null"
Required Use this to set your hostname. Should be set as an environment variable. This will usually be something like GHQ123.example.com. This value is required.
WEBDRIVER_DRIVER "null"
Use this to override the target browser. The standard values are shown below. These will typically be set via Maven profile options. Valid options can be found in the Selenium 2 docs.
SINGLE_SAUCE "null"
Use this to target a single SauceLabs browser (instead of the default suite). This will typically be set via Maven profile options. If no WEBDRIVER_DRIVER or SINGLE_SAUCE target is specified, the default suite of all SauceLabs browsers will be run (in parallel). These values can be used to specify a SINGLE_SAUCE target.
- firefox:5
- iexplore:7
- iexplore:8
- iexplore:9
- chrome:5
SAUCELABS_USER "null" - Required
Use SauceLabs sub-accounts when possible - one account for each user and one per build agent.
SAUCELABS_KEY "null" - Required
Use SauceLabs sub-accounts when possible - one account for each user and one per build agent.
SAUCELABS_SERVER "ondemand.saucelabs.com/wd/hub"
Use to override the SauceLabs target URL. You will almost certainly never need to touch this.
You can get a nice spreadsheet (in CSV format) of how long your browser tests are taking to execute. Just add the following to your logback-text.xml file:
target/selenium-timings.csv true %msg%nAn example of this can be found in webtest-sample. Note that each time you run the test suite, it adds the timing values to the file. So, you could run the following commands:
mvn clean verify mvn verify mvn verify
...and you would get three sets of timing data in one file. With the configuration above, the resulting timing data can be found in the file target/selenium-timings.csv. You can open this file up in Excel and convert it to a Pivot Table for easy analysis. Pivot Tables in Excel are beyond the scope of this document, but if you don't know how they work, find someone who does and they can show you in a few minutes.
By default, webtest-sample builds the WAR that is tested. In many cases, you may want to test a WAR that was built by another project and released to a Maven Repository. //TODO post an example of this. Some of the highlights include:
- Make sure the package type for the webtest project is set to "jar".
- Add the "finalName" attribute to the build, referring to the project under test.
- Use the maven-dependency-plugin to pull the correct project war file in during the generate-resources phase (as per the previous implementation with jetty).
- Override the default values for path, warDirectory, warFile, and ignorePackaging in the Tomcat plugin configuration block so that the project under test is used to build the webapp.
parallel-webtest introduces a new utility object called Path. This object is used to isolate your tests from the target URLs, ports, etc. Normally you will configure Path objects in code, not via these settings. To understand this, consider the most basic command in parallel-webtest: driver.get("http://localhost:8080/myapp/"); This command is problematic for several reasons. It's hard-coded to localhost, which means that it may very well not work on a build agent, and certainly won't work on SauceLabs. Same with hard-coding the port as 8080. Instead, you want to use code something like this: Path p = new Path();
@Before
public void initPath()
{
p.setContext("/myapp");
}
@Test
public void firstTest() throws Exception {
driver.get(p._("/"));
assertTrue(driver.getPageSource().contains("Some Text"));
}
This model isolates the test from the configuration of the system. The server name and ports will automatically change. The context is set in a single place, which reduces typing and makes the test more generic. The one little odd thing you may not be used to is the method _ (just an underscore) on the Path object. It's just a method with a strange name that converts the string passed in to the full value.
By default, the Path object will automatically initialize itself with the the local system name (WEBTEST_HOSTNAME), http, and 8080. You can use the configuration values above to configure different profiles (for example, if you have a profile set up to detect running on a continuous integration server). Normally, you would use one (or more) Path objects in your code to configure things. For example, you might use two Path objects to keep track of two servers (say, a shared login system and the application target). You would use the defaults when possible, and selectively override as needed. These values can be set to allow you to selectively override the defaults, depending on your desired target. For example, let's say that you want to override the entire suite to point to a shared dev environment running https. You could then specify the WEBDRIVER_PROTOCOL=https and WEBDRIVER_SERVER=shared3-dev.example.com, and all Path objects will then default to those values (including automatically picking up the port as 443).
Whatever strategy you use, remember to keep your Path objects as generic as possible to facilitate reuse, and avoid copy-and-paste.
== Default Path Object Configuration == These properties can be used to change the default values generated by the Path object.
WEBDRIVER_PROTOCOL "null"
Use this to set the default protocol value. This is usually either http (default) or https.
WEBDRIVER_SERVER "null"
Use this to set the default server target. This will default to the GHC_HOSTNAME (if running locally) or agent.name (if running on a build agent).
WEBDRIVER_PORT "null"
Use this to override the port. This will default to 443 (if protocol is set to https), 8080 (if running locally) or 80 (if running on a build agent).
WEBDRIVER_CONTEXT "null"
Use this to specify the context root.