top of page
hand-businesswoman-touching-hand-artificial-intelligence-meaning-technology-connection-go-

Why do we use PicoContainer in cucumber?

What is PicoContainer?


PicoContainer is a lightweight and extensible dependency injection (DI) container framework for Java applications. It is designed to manage and resolve dependencies between various components of an application, making it easier to develop and maintain complex software systems. It helps developers write more modular, maintainable, and testable code by promoting loose coupling between components. Here, we are going to use constructor injection method where constructor of a class is used to pass dependencies.


What is the need for PicoContainer?


Sometimes while working on a large scale BDD automation framework, we might have to share common steps among multiple scenarios. The scenarios can be in a single feature file or multiple feature files. Passing test state from one step definition to another can be easily achieved using instance variables, but that only works for elementary and small projects.


Let's have a look at the following scenario written in gherkin in a UI automation demo project:


Feature: Attendance details popup verification Background: Admin click +Add New Attendance button in Manage attendance page Given Admin is in attendance details popup window #1 Scenario: Validate valid program name is reflecting in the dropdown When Admin clicks program name dropdown in attendance details popup Then Program Name in the drop down should match with program name in manage program page table in attendance details popup

#2 Scenario: Validate valid class name is reflecting in the dropdown When Admin clicks class name dropdown in attendance details popup Then Class Name in the drop down should match with class name in manage class page table in attendance details popup


In the above scenarios, we have to access the variable programName and className from another class for validation. Inheritance is not possible in Cucumber step definition class. And if we don't want to create objects for dependent classes in our step definition file, dependency injection is the ideal solution.


Implementation

To use PicoContainer with Maven, add the following dependency to your pom.xml:

<dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-picocontainer</artifactId> <version>7.13.0</version>

</dependency>


TestBase.java


public class TestBase { public WebDriver driver; public WebDriver WebDriverManager() throws IOException { FileInputStream fis=new FileInputStream(System.getProperty("user.dir")+"//src//test//resources//global.properties"); Properties prop = new Properties(); prop.load(fis); String url=prop.getProperty("LmsUrl"); String browser_properties=prop.getProperty("browser"); String browser_maven=System.getProperty("browser"); String browser = browser_maven!=null ? browser_maven : browser_properties; if(driver == null) { if(browser.equalsIgnoreCase("chrome")) { driver = new ChromeDriver(); } if(browser.equalsIgnoreCase("firefox")) { driver = new FirefoxDriver(); } driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5)); driver.get(url); } return driver; } }


The test base class does the driver initialization and reads the LmsUrl from the global.properties file.

We are assuming user is successfully logged into the application and clicked on the Attendance link from the dashboard and clicked on the +Add New Attendance button and currently on the Attendance details popup window.


TestContextSetup.java


import java.io.IOException;

import org.openqa.selenium.WebDriver;


import pages.PageObjectManager;

public class TestContextSetup {

public WebDriver driver;

public PageObjectManager pageObjectManager;

public TestBase testBase;

public GenericUtils genericUtils;

public String className;

public String programName;


public TestContextSetup() throws IOException{

testBase = new TestBase();

pageObjectManager = new PageObjectManager(testBase.WebDriverManager());

genericUtils = new GenericUtils(testBase.WebDriverManager());

}

}


AttendancePage.java


public class AttendancePage { public WebDriver driver;

public AttendancePage(WebDriver driver) { this.driver=driver; PageFactory.initElements(driver, this); }

public String getDropdownClassName() { String dropdownClassname = new Select(classNameDropdown).getFirstSelectedOption().getText(); return dropdownClassname; } public String getDropdownProgramName() { String dropdownProgramname = new Select(programNameDropdown).getFirstSelectedOption().getText(); return dropdownProgramname; }


AttendancePageStepDefinition.java


public class AttendancePageStepDefinition { AttendancePage attendancePage; public WebDriver driver; TestContextSetup testContextSetup; public AttendancePageStepDefinition(TestContextSetup testContextSetup) { this.testContextSetup=testContextSetup; this.attendancePage =testContextSetup.pageObjectManager.getAttendancePage(); }

It is important to pass the testContext setup instance in the constructor of the step definition. Here, using dependency injection we are successfully accessing the variables programName and className which is assigned values in respective page class and validating it against the value from the dropdown in the popup window.


Advantages of using PicoContainer


Here are some key points about PicoContainer:

  1. Dependency Injection: PicoContainer follows the principles of dependency injection, where the dependencies of an object are injected into it rather than the object creating its own dependencies. This promotes loose coupling and makes your code more maintainable and testable.

  2. Lightweight: PicoContainer is known for its simplicity and lightweight nature. It doesn't come with many of the advanced features of larger DI frameworks like Spring, but this can be an advantage when you need a simple solution for dependency injection without the complexity of a full-fledged framework. It doesn’t require your classes to use any APIs.

  3. Component Registration: In PicoContainer, you register your components (Java objects) along with their dependencies in the container. PicoContainer then takes care of resolving these dependencies and providing the necessary components when they are needed.

  4. Lifecycle Management: PicoContainer can manage the lifecycle of your components, including their creation, initialization, and disposal. This is particularly useful for managing resources and ensuring that objects are properly cleaned up when they are no longer needed. It only has a single feature – it instantiates objects.

  5. No XML Configuration: Unlike some other DI containers, PicoContainer typically doesn't rely on XML configuration files. Instead, you configure your container and its components in Java code, which can be more intuitive for some developers.


Cucumber supports several DI modules: PicoContainer, Spring, Guice, OpenEJB, Weld, and Needle. One of the key features of PicoContainer is its simplicity. It is easy to learn and use, with a small codebase and a straightforward API. It also supports multiple configuration formats, such as XML, annotations, and programmatic configuration.


Conclusion

PicoContainer is a useful choice when you need a simple and lightweight dependency injection framework for your Java projects. In order to share states between different scenarios and to avoid multiple instances of objects PicoContainer can be used. It will simply create and inject dependencies through constructor of classes.


I hope you find this blog useful.


Thanks and Happy Coding!!

426 views1 comment

1 Comment

Rated 0 out of 5 stars.
No ratings yet

Add a rating
Guest
Sep 20, 2023
Rated 5 out of 5 stars.

Great article!

Like
bottom of page