Question

In Cucumber (the ruby version) you can easily call steps from other steps and thus build hierarchical libraries of steps making it easy to write the Gherkin feature specifications in the most generic terms.

However it is not readily apparent how to do this in Cucumber-JVM and I have been unable to find documentation for it.

Let me be clear I am not interested in calling the step implementation function directly because I don't want to have to know what its signature is, nor to change the call every time the implementation changes.

Rather, I want to pass an arbitrary string that will go through the regex matcher and automatically find the matching step and execute it. Just as the engine runs all steps.

simple example of what I would expect syntax to look like to define synonym "logout":

When("user logs out") { () =>
  d.executeScript("logout();")
}
When("logout") { () =>
  Step("user logs out")
}
Était-ce utile?

La solution

This functionality is not supported in Cucumber-JVM. (Note that the Cucumber Backgrounder document you link in your question describes using Steps within Steps as "an anti-pattern")

Essentially, we believe that Cucumber is a collaboration tool and that Gherkin is not a programming language.

You can see a longer discussion of how we arrived at this decision here

Autres conseils

Calling steps within steps is a terrible anti-pattern that can easily be replaced by something much simpler.

Instead of one step calling another step, have both steps call the same helper method.

If you apply this pattern with rigour you and up with

  • step definitions that are all just single calls to helper methods
  • a suite of helper methods that collectively provide a test-api

The art of elegantly implementing your Cucumber scenarios now becomes a known programming problem as all your functionality is now directly in code in your programming language rather than being in some restrictive construct specific to Cucumber.

You can now

  • refactor your helper methods to provide cleaner interaces
  • use parameters to give methods greater power
  • use naming to give all your calls greater clarity
  • use a helper method as an entry point to a suite of extra functionality
  • use delegation to move functionality out of helper methods and into test service objects ...

Providing this separation can be initially challenging if you are not a programmer or not experienced in the particular programming language in use. However once you get past this initial hurdle the code you can and should produce will be much easier to work with than the tangled mess that inevitably occurs with step nesting.

To call steps within step definitions, inherit cuke4duke.Steps in java

import cuke4duke.StepMother;
import cuke4duke.Steps;
import cuke4duke.annotation.I18n.EN.When;

public class CallingSteps extends Steps {
    public CallingSteps(StepMother stepMother) {
        super(stepMother);
    }

    @When("^I call another step$")
    public void iCallAnotherStep() {
        Given("it is magic"); // This will call a step defined somewhere else.
    }
}

Example: https://github.com/cucumber-attic/cuke4duke/blob/master/examples/java/src/test/java/simple/CallingSteps.java

Note: cuke4duke support scala as well

In Cucumber each Step is a Method. That way, you can call other methods in any step that you want.

@When("^click on \"([^\"]*)\"$")
public void clickOn(String arg1) throws Throwable {
    driver.findElement(By.linkText(arg1)).click();
}


@Then("^should see the static elements changing$")
public void shouldSeeTheStaticElementsChanging() throws Throwable {
    clickOn(); 
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top