What is the Selenium Service Builder
If I would ask How can we create a new WebDriver in Selenium? Most of the QAs would write a code like the following.
driver = new ChromeDriver();
And the Project structure would be pretty much like this
public class Example {
private WebDriver driver;
@BeforeEach
public void setup() {
driver = new ChromeDriver();
driver.get("https://medium.com/@serhat-ozdursun");
}
@Test
public void someTest() {
assertTrue(true);
}
@AfterEach
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
}
And It is not wrong, but have you ever wondered what is happening when you initialize a new WebDriver? I’ll basically explain this without going into all the technical details.
As you know there should be a browser driver executable file. The browser driver executable is a separate program or binary that acts as a communication bridge between the WebDriver client library (such as Selenium) and the web browser. It is responsible for launching the browser, establishing a connection, and executing commands sent by the WebDriver client library.
Each browser has its own specific driver executable. For example:
- ChromeDriver: The driver executable for Google Chrome.
- GeckoDriver: The driver executable for Mozilla Firefox.
- EdgeDriver: The driver executable for Microsoft Edge.
- SafariDriver: The driver executable for Safari (for macOS and iOS).
There is a class in the Selenium library it is called DriverService
. The DriverService
class in Selenium is a part of the Selenium WebDriver API that manages the lifecycle of the browser driver executable. It is used to start and stop the browser driver, which acts as a bridge between the WebDriver client library and the actual browser.
The DriverService
class provides methods to configure and control the behavior of the browser driver executable. It allows you to set various properties and options for the driver, such as the path to the driver executable, the port on which the driver should listen for commands, and the logging preferences.
Note that the DriverService
class is specific to each browser driver. For example, there are different classes for ChromeDriver, GeckoDriver (Firefox), and EdgeDriver. Each driver has its own specific options and methods, but they all provide similar functionality for managing the lifecycle of the driver executable.
Now, You have enough context to explain what does happening once you initialize a new ChromeDriver or other browsers Driver.
When you initialize a new ChromeDriver first Selenium starts a DriverService to manage the browser driver executable. Afterward, DriverService gets the browser driver executable started. In that sense probably, you would have a life cycle for your automation tests like the following
public class Example {
private WebDriver driver;
@BeforeEach
public void setup() {
driver = new ChromeDriver();
driver.get("https://medium.com/@serhat-ozdursun");
driver.manage().window().fullscreen();
}
@Test
public void someTest() {
assertTrue(true);
}
@Test
public void someTest1() {
assertTrue(true);
}
@Test
public void someTest2() {
assertTrue(true);
}
@Test
public void someTest3() {
assertTrue(true);
}
@Test
public void someTest4() {
assertTrue(true);
}
@AfterEach
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
}
This example has 4 tests, and a new ChromeDriver gets initialized before each test. So now You know that it means the Selenium gets DriverService starts 4 times and it gets the browser executable 4 times as well. The same things will happen to tear down ChromeDriver. The DriverService gets the browser executable session deleted 4 times and then The Selenium gets the initiated DriverService remove 4 times.
This process causes time wasting. If you have a lighter test project that let’s say includes 100–200 tests this time can be afforded. But What if you are working on a heavy test project? and What if there is a better way to manage the browser driver executable?
We can start the DriverService and the Browser Driver Executable separately. If we would write the same test class in that sense it would be like the following.
public class ServiceBuilderExample {
private static DriverService service;
private WebDriver driver;
@BeforeAll
static void beforeAll() {
service = new ChromeDriverService.Builder()
.usingAnyFreePort()
.build();
try {
service.start();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@BeforeEach
public void setup() {
var option = new ChromeOptions();
option.addArguments("--start-fullscreen");
driver = new RemoteWebDriver(service.getUrl(), option);
driver.get("https://medium.com/@serhat-ozdursun");
}
@Test
public void someTest() {
assertTrue(true);
}
@Test
public void someTest1() {
assertTrue(true);
}
@Test
public void someTest2() {
assertTrue(true);
}
@Test
public void someTest3() {
assertTrue(true);
}
@Test
public void someTest4() {
assertTrue(true);
}
@AfterEach
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
@AfterAll
static void afterAll() {
service.stop();
}
}
In this example: The selenium will start the DriverService with @BeforeAll annotation. So The DriverService gets started only one time during the test execution. BeforeEach the method we will give the URL of the already started DriverService to the Selenium RemoteDriver class and It will execute tests on the service that working on that URL, You can consider this exact same with the Selenium grid.
With the AfterEach method, Selenium deletes the Browser Driver Executable session with the command driver.quit(); But the DriverService still running to accept the new Browser Driver Executable.
After all test methods are executed, In the AfterAll method the DriverService gets stopped.
In other words, it will apply the same test methods, but this time DriverService is started once and stopped once during the test execution. So it will reduce the test execution time.
Let's see that it reduces what time for the project that includes only 4 test methods.
The test execution time will be 22 sec 644 ms if we don’t start the DriverService only one time for execution
But If we use the DriverService start one time in the BeforeAll method, The test execution time is 18 sec 421 ms
So as you can see, we earn approximately 5 sec only for 4 test methods. You can imagine what time we can earn in heavy test projects with this approach.
Also, It is better the mention, It is not the only reason to use DriverService It also provides many many methods to manage the Browser Driver. For instance, you can manage the Service port or define the log level, executable driver file path and there are many others. The methods change based on the browser.
I hope this has been a useful article for everyone. If you want more articles like this, please follow me and share this with others.
Class Examples: https://rb.gy/h8sxa
Note: I've used ChatGPT for some details.