Stéphane GRILLON
Stéphane GRILLON

Reputation: 11864

how use optional parameters in cucumber

I want the same Gherkin sentence (with paramaters and without paramaters):

Gherkin with paramaters:

When a 'notify' message is sent to the green box with the properties.
 |type|message|
 |error|The error message|

Gherkin without paramaters:

When a 'notify' message is sent to the green box with the properties.

Java (cucumber):

@When("^a '(.*)' message is sent to the green box with the properties.$")
public void hello(String name, List<GherkinCondition> conditions) {
    ...
}

I have a error because java method is is declared with 2 parameters and in the case "without paramaters" I have only one.

stack trace:

cucumber.runtime.CucumberException: Arity mismatch: Step Definition 'steps.CommonSteps.hello(String,GherkinCondition>) in file:/C:/workspace/xxxxx/java/target/classes/' with pattern [^a '(.*)' message is sent to the green box with the properties.$] is declared with 2 parameters. However, the gherkin step has 1 arguments [notify]. 

Upvotes: 4

Views: 23377

Answers (8)

Swati Goyal
Swati Goyal

Reputation: 1

Regex can help you send the optional params from the test definition to step definition, see below example:

When(/^"([^"]*)" marks the trip arrived(?: at buyer "([^"]*)")?(?: with)?(?: (.*))*$/) do |user_type, buyer_name, table|
  params = table ? table.rows_hash : {}
  <rest of the code here>
end

Then you can send as many kv in the table.

Upvotes: 0

Yub Raj
Yub Raj

Reputation: 49

Till now, there is no solution for this;

Alternative text only works when there is no whitespace between the alternative parts.

Hence your way of using () -> optional is the best we have now.

Upvotes: 0

V&#237;ctor
V&#237;ctor

Reputation: 677

Can't say how to solve this problem specifically in Java, but when using PHP I think you can achieve what you aim at by setting your param to NULL, i.e.:

Imagine you want to check colors, and your Gherkin states something like:

Given I want to check colors "red" and "green"

You'd have a function such as this one:

public function iCheckColors($arg1, $arg2) {
    // do stuff here;
}

Then you might want to check three colors in your Gherkin line, such as:

Given I want to check colors "red" and "green" and "blue"

In this case, you'd need to add this third param to your function:

public function iCheckColors($arg1, $arg2, $arg3) {
    // do stuff here;
}

The problem here is, if you were to use the first Gherkin line again, your function would throw an error, since she expects the third param, but if you set this param to NULL:

public function iCheckColors($arg1, $arg2, $arg3 = NULL) {
    // do stuff here;
}

Then both Gherkin lines added to the function should work. It still expects two params and, in case you'll add a third param to your Gherkin line, it'd override the NULL value.

Hope this is what you're trying to achieve.

Upvotes: 0

Robert Van-Vas
Robert Van-Vas

Reputation: 21

I`m doing it this way:

@Then("^Something is (not )?counted$")
public void somethingCounted(String optional) {
    //
}

Regex matches both "Something is counted" and "Something is not counted"

For the first case, you'll get "not" value, for the second case you`ll get null.

Upvotes: 2

St&#233;phane GRILLON
St&#233;phane GRILLON

Reputation: 11864

I create a PR for resolve this problem: https://github.com/cucumber/cucumber-jvm/pull/1056

Gherkin script test:

@hello 
Feature: hello (Function to validate the environment.) 

    Scenario Outline: Function to validate the environment.
        Given me a hello, please. Best Regards '<author>'.
        Given me a hello, please. Best Regards '<author>'.
            |key|expected|actual|
        Given me a hello, please. Best Regards '<author>'.
            |key|expected|actual|
            |zip|35000|<zip>|
            |city|Rennes|<city>|

        Given me a bye, please. Best Regards '<author>'.
        Given me a bye, please. Best Regards '<author>'.
            |zip|<zip>|
            |city|<city>|

        Given me a cat, please. Best Regards '<author>'.

    Examples:
    #Begin Examples#
    |author|zip|city|
    |Jenkins Q1|35000|Rennes|
    |Jenkins Q2|35000|Rennes|
    #End Examples#

Java Cucumber code:

    @Given("^me a hello, please. Best Regards '(.*)'.$")
    public void hello(String name, List<GherkinCondition> conditions) {
        int i = 0;
        for (GherkinCondition gherkinCondition : conditions) {
            i++;
            logger.info(String.format("  expected contition N°%d=%s", i, gherkinCondition.getExpected()));
            logger.info(String.format("  actual   contition N°%d=%s", i, gherkinCondition.getActual()));
        }
        logger.info("Hello " + name + "!");
    }

    @Given("^me a cat, please. Best Regards '(.*)'.$")
    public void hello(String name) {
        logger.info("Take my cat " + name + "!");
    }

    @Given("^me a bye, please. Best Regards '(.*)'.$")
    public void bye(String name, Map<String, String> params) {
        int i = 0;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            i++;
            logger.info(String.format("  Key N°%d: %s   Value:%s", i, entry.getKey(), entry.getValue()));
        }
        logger.info("Bye " + name + "!");
    }

Upvotes: 1

Kripal Singh Thakur
Kripal Singh Thakur

Reputation: 3

I got the ans of my problem:-

@When("^I search (.*) in( IND| USA)? Database$")

I was looking for optional parameter either USA or IND. above line fix my problem. spaces are needed after ( and |

Upvotes: 0

Kripal Singh Thakur
Kripal Singh Thakur

Reputation: 3

This works for me. I can pass either IND or USA. Note: this would not work if you don't pass any IND,USA.

@When("^I search (.*) (IND|USA)? in Database$")
public void searchInDatabase(String name, String country){
    if(country.equals("IND"))
        dbObj.searchDatabase(name, true);
    else if(country.equals("USA"))
        dbObj.searchDatabase(name, false);
    else
        dbObj.searchDatabase(name, true); 
}

Upvotes: 0

Grasshopper
Grasshopper

Reputation: 9058

Cucumber step definitions do not support optional parameters.

Either you write two different step definitions or you can give an empty datatable for the second case.

When a 'notify' message is sent to the green box with the properties.
 |type|message|

or even

When a 'notify' message is sent to the green box with the properties.
     |||

Upvotes: 5

Related Questions