After moving from Cucumber-JVM 2.X to Cucumber-JVM 5.5.0 I'm faced problem with existing step defs which use regular expression and optional capture group.
For version 2.X when there is no optional text in gherkin step then step definition method got null value.
For version 5.5.0 if I don't supply optional text in gherkin step then I ended up with exception.
Scenario
Scenario: cucumber expression vs regular expression
And text aaaa text2
And text text2
GlueCode
@Given("^text(?: (.+))? text2$")
public void optionalCaptureGroup(String optionalGroup) {
System.out.println(optionalGroup);
}
@ParameterType(".+")
public String paramType1(String s) {
return s;
}
Exception
io.cucumber.core.exception.CucumberException: Could not convert arguments for step [^text(?: (.+))? text2$] defined at 'migrate.ParameterTypeStepDefinition.optionalCaptureGroup(java.lang.String)'.
The details are in the stacktrace below.
at io.cucumber.core.runner.PickleStepDefinitionMatch.couldNotConvertArguments(PickleStepDefinitionMatch.java:119)
at io.cucumber.core.runner.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:56)
at io.cucumber.core.runner.TestStep.executeStep(TestStep.java:64)
at io.cucumber.core.runner.TestStep.run(TestStep.java:49)
at io.cucumber.core.runner.PickleStepTestStep.run(PickleStepTestStep.java:46)
at io.cucumber.core.runner.TestCase.run(TestCase.java:51)
at io.cucumber.core.runner.Runner.runPickle(Runner.java:66)
at io.cucumber.core.runtime.Runtime.lambda$run$2(Runtime.java:100)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
at java.util.concurrent.FutureTask.run(FutureTask.java)
at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:243)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at io.cucumber.core.runtime.Runtime.lambda$run$3(Runtime.java:100)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.stream.SliceOps$1$1.accept(SliceOps.java:204)
at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1359)
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:499)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:486)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at io.cucumber.core.runtime.Runtime.run(Runtime.java:101)
at io.cucumber.core.cli.Main.run(Main.java:75)
at io.cucumber.core.cli.Main.main(Main.java:31)
Caused by: io.cucumber.cucumberexpressions.CucumberExpressionException: ParameterType {paramType1} failed to transform [] to class java.lang.String
at io.cucumber.cucumberexpressions.ParameterType.transform(ParameterType.java:237)
at io.cucumber.cucumberexpressions.Argument.getValue(Argument.java:67)
at io.cucumber.core.stepexpression.ExpressionArgument.getValue(ExpressionArgument.java:15)
at io.cucumber.core.runner.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:47)
... 25 more
Caused by: io.cucumber.core.backend.CucumberBackendException: Failed to invoke public java.lang.String migrate.ParameterTypeStepDefinition.paramType1(java.lang.String)
at io.cucumber.java.Invoker.invoke(Invoker.java:29)
at io.cucumber.java.JavaParameterTypeDefinition.execute(JavaParameterTypeDefinition.java:81)
at io.cucumber.cucumberexpressions.ParameterType.transform(ParameterType.java:233)
... 28 more
Caused by: java.lang.IllegalArgumentException: wrong number of arguments
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at io.cucumber.java.Invoker.invoke(Invoker.java:27)
... 30 more
My questions are:
1. why I'm getting exception about wrong number of arguments - were there any changes in handling of optional capturing group since version 2.X?
2. Why cucumber want to interact with custom type parameter in the case when step definition use pure regular expression?
So I deleted my previous answer because it was wrong. Looks like there is a bug in the way Cucumber handles optional parameter types.
You can work around it by defining a parameter type that takes an array as an argument.
@ParameterType(value = ".+")
public String paramType1(String... s) {
if (s.length > 0) {
return s[0];
}
return null;
}
Normally this would be used for parameter types with multiple capture groups but it works in these circumstances too.
@ParameterType(value = "([a-z]+)([0-9]+)")
public String paramType1(String... s) {
}