“Building Robust Test Automation Framework : Factory Design Pattern”

Smruti Sourav Sahoo
4 min readApr 6, 2024
Photo by Fernando Hernandez on Unsplash

Introduction:

In the realm of software testing, efficiency, maintainability, and scalability are paramount. As Software Development Engineers in Test (SDETs), we constantly seek ways to streamline our testing processes while ensuring robustness and reliability. One powerful tool in our arsenal is the Factory Design Pattern, which offers a structured approach to object creation. In this blog post, we’ll explore how SDETs can leverage the Factory Design Pattern in the context of browser factory for Selenium testing, enhancing code organization, reusability, and maintainability.

Understanding the Factory Design Pattern:

Factory Design Pattern is a creational design pattern that provides an interface for creating objects in a superclass but allows subclasses to alter the type of objects that will be created.

This pattern promotes loose coupling, encapsulation, and separation of concerns by abstracting the object creation process from the client code.

The most crucial reason for using the Factory Design Pattern in test automation is to promote code maintainability.

By encapsulating object creation logic within factory classes, the Factory Design Pattern centralizes and organizes this code, making it easier to manage, update, and extend. This reduces code duplication, minimizes the risk of errors, and simplifies maintenance efforts as the project evolves.

Ultimately, it ensures that test automation code remains clean, modular, and scalable, which is essential for long-term success and efficiency in testing endeavors.

Problems we are solving with this design pattern:

One common challenge in Selenium testing is managing different types of web browsers (e.g., Chrome, Firefox, Safari) with specific configurations. This is where the Factory Design Pattern shines.

This design pattern best feature is object creation , when we decide which object should get created at runtime only (not pre- meditated).

Without the use of Factory Design Pattern :

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class BrowserTests {

public static void main(String[] args) {
String browserType = "chrome"; // Change browser type here

WebDriver driver;

if (browserType.equalsIgnoreCase("chrome")) {
driver = new ChromeDriver(); // Creating Chrome driver
} else if (browserType.equalsIgnoreCase("firefox")) {
driver = new FirefoxDriver(); // Creating Firefox driver
} else {
throw new IllegalArgumentException("Invalid browser type: " + browserType);
}

driver.get("https://www.example.com");
driver.quit();
}
}

In the code above, we’re using if-else statements to determine the browser type and create the corresponding WebDriver instance. While this approach works, it has some drawbacks:

  1. Code Complexity: As more browser types are added, the if-else chain becomes longer and more complex, making the code harder to read and maintain.
  2. Hardcoded Browser Types: Browser types are hardcoded directly in the test code, making it less flexible to switch or add new browser types without modifying the code.
  3. Violation of Single Responsibility Principle: The test code is responsible for both test logic and browser handling, violating the principle of single responsibility.

With Factory Design Pattern :

To implement the Factory Design Pattern in our browser factory for Selenium testing, we’ll follow these steps:

UML Diagram for Factory Design Pattern
  1. Define the WebDriverFactory interface:
public interface WebDriverFactory {
WebDriver createWebDriver();
}

2. Implement concrete factories for each browser type:

public class ChromeDriverFactory implements WebDriverFactory {
@Override
public WebDriver createWebDriver() {
return new ChromeDriver();
}
}

public class FirefoxDriverFactory implements WebDriverFactory {
@Override
public WebDriver createWebDriver() {
return new FirefoxDriver();
}
}

// Add more factories for other browser types as needed (e.g., SafariDriverFactory)

3. Utilize the factory in test code:

public class BrowserTests {
private WebDriver driver;

@BeforeMethod
public void setUp() {
WebDriverFactory factory = new ChromeDriverFactory();
// Change factory based on browser preference
driver = factory.createWebDriver();
}

@AfterMethod
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
}

By leveraging the Factory Design Pattern in our browser factory for Selenium testing, SDETs can reap several benefits:

  1. Modularity: The separation of browser creation logic into factory classes enhances modularity, making it easier to manage and maintain.
  2. Flexibility: Adding support for new browser types or configurations becomes straightforward by extending the factory hierarchy.
  3. Reusability: The factory classes can be reused across multiple test classes and projects, promoting code reuse and reducing duplication.
  4. Scalability: As the testing requirements evolve, the Factory Design Pattern accommodates scalability without significant modifications to existing codebase.

Conclusion :

In the dynamic landscape of software testing, effective test automation practices are essential for ensuring product quality and accelerating time-to-market.

The Factory Design Pattern serves as a valuable tool for SDETs, empowering them to streamline browser factory implementation in Selenium testing environments.

By adopting this pattern, SDETs can enhance code organization, reusability, and maintainability, ultimately driving efficiency and effectiveness in their testing endeavors.

Armed with this knowledge, SDETs can leverage the power of design patterns to elevate their testing practices and contribute to the success of their projects.

Enjoyed the Guide? Give Us a Clap!

Have Feedback or Questions? Share Them in the Comments!

Do follow us for more updates.

Thanks for Reading !!

--

--