Parallel JUnit 4 and Selenium - Part One: Parameters

Posted Oct 20th, 2010

Though not the first testing framework created, JUnit has garnered plenty of mainstream attention and created a wave of followers.

One of these is TestNG, which was created to address, among other things, the difficulty of passing parameters into scripts, as well as run scripts in parallel. For these reasons, the Selenium community has largely chosen TestNG as the framework of choice. But JUnit 4 can also address these topics using the @RunWith annotation and a custom runner.

This is part one in a series of posts illustrating how to create parameterized, parallel scripts that can be run either on your local infrastructure or on Sauce OnDemand.

Before we start into code, here's a bit of context. I've been writing test frameworks and harnesses for a decade now and know the frustration of finding half answers online that have been stripped down for easy blog post write-ups. The intent of my post is to not inflict you with that experience. Instead, I'll discuss parallel execution in the context of a full project - complete with Maven pom.xml and all headers in their proper places. There will be places in this post where they are omitted, so you are recommended to clone the Sauce Labs Parallel Test Examples github repo.

We begin our journey with @RunWith(Parameterized.class). This annotation will iterate over each test method with a set of parameters of your choosing. For Selenium scripts, the part that begs for parallelization is the browser, so that is what we will parameterize first.

Have a look at, as there are a couple of interesting things beyond the standard @Before, @Test and @After.


import java.util.Collection;
import java.util.List;
import java.util.Arrays;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;

public class TestParameters {
    private Selenium selenium;
    private String browser;
    public TestParameters(String browser){
        this.browser = browser;
    public static Collection browsersStrings(){
      return Arrays.asList(new Object[][] { {"*firefox"}, {"*googlechrome"} });

    public void setUp() throws Exception {
        selenium = new DefaultSelenium("localhost", 4444, this.browser, "http://localhost:3000");
    public void testSauce() throws Exception {"/");
        assertEquals("Cross browser testing with Selenium - Sauce Labs", this.selenium.getTitle());

    public void tearDown() throws Exception {

The first thing that sticks out is the @RunWith class annotation. While there are a number of different runners floating around, we are using the Parameterized one that comes with JUnit itself. With this in place, JUnit will look for a method annotated with @Parameters to use as arguments to the constructor. In this case, we currently only have one parameter, which we set as this.browser. Of course, this is then used when launching the browser in @Before.
And how does this address parallelization? Well, the @parameters method must return a Collection that is then iterated over, so you end up executing testSauce twice - the first time with "*firefox" and then with "*googlechrome."

This is cool from a technical perspective, but has two pretty big flaws. First, the Java code needs to be edited to change browsers, and second, by executing serially, the time it takes to run the scripts increases 100% for every browser added. We'll address both of those starting with external loading of our @Parameters in the next post of the series.

Written by

Adam Goucher


SeleniumUnit Testing