Selenium and Cucumber JVM 4 Parallel Execution using ThreadLocal WebDriver and PicoContainer

Introduction

Cucumber-JVM 4 supports parallel execution across threads out of the box and also with JUnit and TestNG. The easiest way to integrate Selenium with Cucumber in parallel mode is to use Before and After hooks to create and close the driver respectively. But this is expensive and time consuming.

This article will look at allocating a driver to a specific thread and using it for all the scenarios assigned to the thread. The driver will only be closed at the end of the test execution. The drivers will be stored in a ThreadLocal object. Cucumber implementation of PicoContainer will be used for creating and sharing objects.

Source Code

The source code for JUnit is located here. The source code for TestNG is located here.

DriverFactory Class

The DriverFactory (JUnit/TestNG) class contains the static ThreadLocal field which stores the drivers created for each thread. Below is a brief description of ThreadLocal class from the Java 8 API.

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread.

The DriverFactory class contains static methods to return the driver for a thread, add driver to the ThreadLocal field and remove driver from the ThreadLocal field. This also contains a JVM shutdown hook to quit all the driver instances.

To access the driver for a thread in a StepDefinition or PageObject class, DriverFactory.getDriver() is used.

SharedDriver Class

The SharedDriver (JUnit/TestNG) class contains the logic for creating the concrete driver object and adding the driver to the ThreadLocal field of the DriverFactory. Before a new driver is created a check is performed to verify if a driver for the thread already exists. The main purpose of this class is to allow PicoContainer to instantiate the driver.

StepDefinition Class

Cucumber implementation of PicoContainer uses constructor injection. The StepDefinition (JUnit/TestNG) constructor should have a SharedDriver object as the first parameter followed by PageObject object parameters, that the class requires. These objects will be created and injected into the StepDefinition object.

For each scenario and each row of a scenariooutline, new instance of all step defintion and hook classes are created. If multiple step definition classes have the same class(es) injected into their constructor, then the same instance of these objects are injected into all the step definition objects.

JUnit Runner

When using JUnit in parallel mode, all scenarios in a feature file will be executed in the same thread. The two scenarios in feature1.feature file will be executed in one browser. The single feature2.feature will be executed by another thread in a separate browser.

Maven failsafe plugin will be used for parallel execution. Refer to the POM for configuration details.

For more details about parallel execution in JUnit refer to this article.

TestNG Runner

When using TestNG in parallel mode, scenarios can be executed in separate threads irrespective of which feature file it belongs too. Different rows in a scenario outline can be also executed in separate threads. The two scenarios in feature1.feature file will be executed by two threads in two browsers. The single feature2.feature will be executed by another thread in a separate browser.

Maven failsafe plugin will be used for parallel execution. Refer to the POM for configuration details.

For more details about parallel execution in TestNG refer to this article.

Maven Execution

The POM needs to be executed using the Maven command “mvn clean install” or a similar one which executes the maven failsafe plugin integration-test phase.

Leave a Reply

Your email address will not be published. Required fields are marked *