How to pass variables between cucumber-jvm steps

troig picture troig · Oct 17, 2014 · Viewed 81.2k times · Source

To pass variables between steps I have the step methods belong to the same class, and use fields of the class for the passed information.

Here is an example as follows:

Feature: Demo

  Scenario: Create user
    Given User creation form management
    When Create user with name "TEST"
    Then User is created successfully

Java class with steps definitions:

public class CreateUserSteps {

   private String userName;

   @Given("^User creation form management$")
   public void User_creation_form_management() throws Throwable {
      // ...
   }

   @When("^Create user with name \"([^\"]*)\"$")
   public void Create_user_with_name(String userName) throws Throwable {
      //...
      this.userName = userName;
   }

   @Then("^User is created successfully$")
   public void User_is_created_successfully() throws Throwable {
      // Assert if exists an user with name equals to this.userName
   }

My question is if it is a good practice to share information between steps? Or would be better to define the feature as:

Then User with name "TEST" is created successfully

Answer

Pedro Lopez picture Pedro Lopez · Oct 24, 2014

In order to share commonalities between steps you need to use a World. In Java it is not as clear as in Ruby.

Quoting the creator of Cucumber.

The purpose of a "World" is twofold:

  1. Isolate state between scenarios.

  2. Share data between step definitions and hooks within a scenario.

How this is implemented is language specific. For example, in ruby, the implicit self variable inside a step definition points to the current scenario's World object. This is by default an instance of Object, but it can be anything you want if you use the World hook.

In Java, you have many (possibly connected) World objects.

The equivalent of the World in Cucumber-Java is all of the objects with hook or stepdef annotations. In other words, any class with methods annotated with @Before, @After, @Given and so on will be instantiated exactly once for each scenario.

This achieves the first goal. To achieve the second goal you have two approaches:

a) Use a single class for all of your step definitions and hooks

b) Use several classes divided by responsibility [1] and use dependency injection [2] to connect them to each other.

Option a) quickly breaks down because your step definition code becomes a mess. That's why people tend to use b).

[1] https://cucumber.io/docs/gherkin/step-organization/

[2] PicoContainer, Spring, Guice, Weld, OpenEJB, Needle

The available Dependency Injection modules are:

  • cucumber-picocontainer
  • cucumber-guice
  • cucumber-openejb
  • cucumber-spring
  • cucumber-weld
  • cucumber-needle

Original post here https://groups.google.com/forum/#!topic/cukes/8ugcVreXP0Y.

Hope this helps.