cucumberrest-assuredgherkincucumber-java

Gherkin Nested Steps meaning


I am writing Gherkin test cases and Java step definitions in my project. I am new to Gherkin and trying to understand the meaning of nested steps. Can you please help me to understand if the 2nd scenario given involves nested steps?

In my example, I would like to reuse 1st scenario code in 2nd scenario given statement logic. Is there a best way to reuse or rewrite the logic? Note: Below example is written just to explain my question. It may not be a good Gherkin.

Background:
    Given The application is opened

Scenario: Successful Login
    Given the user name and password are entered
    When login button is clicked
    Then user login is successful

Scenario: Add Address Successful
    Given user login is successful
    And Add Address button is clicked
    And user city, country are entered
    when Submit button is clicked

Solution

  • Nested steps refer to calling defined steps inside a "main" one. In your example, the first scenario has the login functionality, which will / can be used in all other scenarios that require the user to be logged in.

    So, the second scenario will have a Given step which calls the login action / steps of the first scenario. There are multiple ways to do this:

    1. If you are defining those steps in the same class, it's just a matter of calling the same methods inside a different step / method.

    Like so:

    public class TestStepsOne {
    
        // Steps from first scenario
    
        @Given("^the user name and password are entered$")
        public void enterUsernamePassword() throws Throwable {
            System.out.println("User and password entered");
        }
    
        @When("^login button is clicked$")
        public void clickLoginButton() throws Throwable {
            System.out.println("Clicked login button");
        }
    
        @Then("^user login is successful$")
        public void isLoggedIn() throws Throwable {
            System.out.println("Logged in!");
        }
    
        // All together
    
        @Given("the user is logged in")
        public void loginSuccessfully() throws Throwable {
            enterUsernamePassword();
            clickLoginButton();
            isLoggedIn();
        }
    }
    

    Now you can use the Given the user is logged in in any scenario, and it will perform the login action.

    2. Using Picocontainer -> details here

    First you need to add these dependencies to your pom.xml:

    <dependency>
        <groupId>org.picocontainer</groupId>
        <artifactId>picocontainer</artifactId>
        <version>2.15</version>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-picocontainer</artifactId>
        <version>1.2.5</version>
    </dependency>
    

    You can separate your step definitions.

    Like so:

    public class TestStepsOne {
    
        // Same as above, without the nested one
    
    }
    

    and second class:

    public class TestStepsTwo {
        private final TestStepsOne testStepsOne;
    
        public TestStepsTwo(TestStepsOne testStepsOne) {
            this.testStepsOne = testStepsOne;
        }
    
        @Given("the user is logged in")
        public void loginSuccessfully() throws Throwable {
            testStepsOne.enterUsernamePassword();
            testStepsOne.clickLoginButton();
            testStepsOne.isLoggedIn();
        }
    }
    

    3. Using cuke4duke -> details here , includes examples

    Like so:

    public class CallingSteps extends Steps {
        public CallingSteps(StepMother stepMother) {
            super(stepMother);
        }
    
        @When("^I call another step$")
        public void iCallAnotherStep() {
            Given("the user is logged in"); // This will call a step defined somewhere else.
        }
    }
    

    Hope this helps