3

I am having difficulty understanding and utilizing dependency injection in my situation. I want to use Pico-container (https://cucumber.io/blog/2015/07/08/polymorphic-step-definitions).

This is my situation...I currently have one step definition class that contains all my selenium, and which is getting way too big:

public class StepDefinitions{
    public static WebDriver driver; // a driver is returned here from a static Driver Factory Class
    LoginPage loginPage = new LoginPage(driver); //Page Object Model(s)

    @Before("setup")
    @After //screen snapshot
    @After("destroy")
    @Given //many methods with this tag
    @When  //many methods with this tag
    @Then  //many methods with this tag
}

Now I want to potentially have one class that contains my driver, POMs, and Hooks:

public static WebDriver driver; //driver is returned from a static Driver Factory Class
LoginPage loginPage = new LoginPage(driver); //Page Object Model(s)

 @Before("setup")
 @After
 @After("destroy")

Another class that contains my @Given, one class that contains my @When, and one class that contains my @Then

I then need to connect everything up right, so all classes can utilize the driver, hooks, and POMs. Cucumber does not support inheritance, so interfaces or Dependency Injection (Pico Container) is the way to go. I do not know how to do this, and I have studied online, I just cannot wrap my poor brain around it all.

snikt
  • 581
  • 4
  • 11
  • 27

2 Answers2

7

You might be interested in my blog post where I use Pico Container to share state between two different Cucumber-JVM step classes, http://www.thinkcode.se/blog/2017/04/01/sharing-state-between-steps-in-cucumberjvm-using-picocontainer

Thomas Sundberg
  • 4,098
  • 3
  • 18
  • 25
  • Why we cant use static instead of pico-container. How static can leak data between scenarios.Can you please give some examples? – Apzal Bahin Dec 19 '19 at 07:03
  • 2
    If you set a static field to something, it will keep the value for the entire life time of the JVM. This means that each test will have to reset the values after its execution. This is possible to do. But if you forget to reset a static variable, it may leak into the next test. So you can use static variables, but they will require you to remember to reset them to avoid leakage. – Thomas Sundberg Dec 24 '19 at 21:01
  • Also, adding to @ThomasSundberg : if static variables are used, then while parallel execution, two or more scenarios might end up overwriting the same static variable! which is again an issue. – Manjunath Prabhakar Jun 16 '21 at 15:15
4

You may not be able to implement inheritance but you can use constructors in step definitions class to pass on driver object reference from one class to another.

  1. Create a base/foundation class that initializes your driver object/ page objects classes. Use @Before annotation for defining setup and @After for defining teardown method.

public class Step_Def_Base {

    public static webDriverCreator test;
        @Before
        public void printScenario(Scenario scenario) {
            test = new webDriverCreator(this.getClass().getSimpleName());
            String className = this.getClass().getCanonicalName();
            System.out.println("********************************************************");
            System.out.println("Scenario: " + scenario.getName());
            System.out.println("********************************************************");
        }

        @After
        public void screenShotAndConsoleLog(Scenario result) {
              test.takescreenshot.takeScreenShotOnException(result);
            if (!(result.getStatus().contains("pass"))) {
                throw new RuntimeException(result.getName() + " got failed");
            }
            test.closeBrowserSession();
        }



}

  1. In your step definition class , create a constructor and instantiate the baseFoundation object with the context. This is where the pico-container plays its magical role of linking the driver object of step definition class with another class.

public class StepDefs_AltoroMutualLoginPage  {

    private Step_Def_Base contextStep;
    private webDriverCreator test;
    public StepDefs_AltoroMutualLoginPage(Step_Def_Base contextStep) {
        // TODO Auto-generated constructor stub
        this.contextStep = contextStep; // <-- This is where pico-containers starts working
        test = contextStep.test; // <-- Linking your driver object reference from the point where it is instantiated , i.e the base foundation class
    }

    @Given("^I am on test fire login page \"([^\"]*)\"$")
    public void alotoroMutualLoginPage(String url) {

        test.launchApplication(url);
        test.altoroMutual.launchLoginLink();
        test.altoroMutual.verifyUserIsOnLoginPage();

    }

Now you can get creative , and organize your page objects accordingly. I aggregated and instantiated all my page object classes inside the wrapper class that is returning the web driver object. You can see in the code, I am accessing altoroMutual pageObject class from test object.

Make sure you are using maven to manage all dev-dependencies . Following dependencies shall add pico container in your project.

        <dependency>
             <groupId>info.cukes</groupId>
             <artifactId>cucumber-picocontainer</artifactId>
              <version>1.2.5</version>
           <scope>test</scope>
        </dependency>
        <dependency>   
            <groupId>org.picocontainer</groupId>  
             <artifactId>picocontainer</artifactId>
             <version>2.14.3</version>
        </dependency>
Manmohan_singh
  • 1,776
  • 3
  • 20
  • 29
  • I appreciate your help, but your code is so far off what I presented. I do not know how I can convert what you wrote to what I am doing. – snikt Jul 02 '18 at 16:39