cucumber/cucumber-jvm

Better error when both DataTable and DocString supplied (was: Arity mismatch discrepancy)

Closed this issue · 4 comments

From @kevlarC on August 3, 2016 8:5

Using version 1.2.4 JVM in junit with either java/scala

Consider this piece of Gherkin.

 When  I POST a request to /some/url with:
      | header        | value            |
      | SomeHeader    | value            |
      | AnotherHeader | value2           |
      | Content-Type  | application/json |
    """
    {
       "member": "value",
       "member": "value2"
    }
    """

And this step method in scala (the same thing happens in java)

  When(s"^I POST a request to ([^ ]*) with:") { (url: String, body: String, headers: DataTable) =>
      println( headers )
      println( url )
      println( body )
  }

the error is:


cucumber.runtime.CucumberException: Arity mismatch: Step Definition 'Quote.scala:13' with pattern [^I POST a request to ([^ ]*) with:] is declared with 3 parameters. However, the gherkin step has 3 arguments [/v4/quote/create, DocString:{
   "till": "GB:a_store_id:a_till_id",
   "currency": "GBP"
}, Table:[[header, value], [TraceId, a_trace_id], [ClientId, a_client_id:a_secret], [Authorization, Bearer:temporary_token], [Content-Type, application/json]]]. 
Step: When I POST a request to /v4/quote/create with:
    at cucumber.runtime.StepDefinitionMatch.arityMismatch(StepDefinitionMatch.java:102)
    at cucumber.runtime.StepDefinitionMatch.transformedArgs(StepDefinitionMatch.java:60)
    at cucumber.runtime.StepDefinitionMatch.runStep(StepDefinitionMatch.java:37)
    at cucumber.runtime.Runtime.runStep(Runtime.java:299)
    at cucumber.runtime.model.StepContainer.runStep(StepContainer.java:44)
    at cucumber.runtime.model.StepContainer.runSteps(StepContainer.java:39)
    at cucumber.runtime.model.CucumberScenario.run(CucumberScenario.java:44)
    at cucumber.runtime.junit.ExecutionUnitRunner.run(ExecutionUnitRunner.java:91)
    at cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:63)
    at cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:18)

Two issues arise

  1. is this valid gherkin ?
  2. the error message obviously is incorrect saying all three parameters are there and it requires 3 parameters ?

Looking at the code it seems to be either of these two lines:

  1. in release 1.2.4 lines 53-57 StepDefinitionMatch.java arityMismatch()
       if (step.getRows() != null) {
            argumentCount++;
        } else if (step.getDocString() != null) {
            argumentCount++;
        }

if the gherkin is correct then this should be a if and then another if not if/else. The parameters might need fixing later on to get the correct items in place.

  1. or 114-116 Ste[DefinitionMatch.java arityMismatch. This should be the same as in 1) i.e. either if/else or if if. Ideally this should use exactly the same code to avoid this bug in the future.

Copied from original issue: cucumber/common#56

You can't have both a data table and a doc string - only one of them. The fix would be to throw an error explaining that more clearly.

I can't reproduce this with 2.0.0-SNAPSHOT. It would appear that the gherkin4 parser doesn't accept it. I reckon the solution would be to make the syntax accept it and have the parser reject it after parsing.

Caused by: gherkin.ParserException$CompositeParserException: Parser errors:
(10:5): expected: #EOF, #TableRow, #StepLine, #TagLine, #ScenarioLine, #ScenarioOutlineLine, #Comment, #Empty, got '"""'
(11:7): expected: #EOF, #TableRow, #StepLine, #TagLine, #ScenarioLine, #ScenarioOutlineLine, #Comment, #Empty, got '{'
(12:10): expected: #EOF, #TableRow, #StepLine, #TagLine, #ScenarioLine, #ScenarioOutlineLine, #Comment, #Empty, got '"member": "value",'
(13:10): expected: #EOF, #TableRow, #StepLine, #TagLine, #ScenarioLine, #ScenarioOutlineLine, #Comment, #Empty, got '"member": "value2"'
(14:7): expected: #EOF, #TableRow, #StepLine, #TagLine, #ScenarioLine, #ScenarioOutlineLine, #Comment, #Empty, got '}'
(15:7): expected: #EOF, #TableRow, #StepLine, #TagLine, #ScenarioLine, #ScenarioOutlineLine, #Comment, #Empty, got '"""'
	at gherkin.Parser.parse(Parser.java:150)
	at gherkin.Parser.parse(Parser.java:125)
	at gherkin.Parser.parse(Parser.java:121)
	at cucumber.runtime.FeatureBuilder.parse(FeatureBuilder.java:56)
	... 19 more

The root cause of the issue can be formulated as "because the Gherkin 2.12.2 parser does successfully produce an AST for steps with both a DocString and a DataTable - even though a step only is allowed to have either a DocString or a DataTable (and not both), an confusing arity missmatch exception message is displayed."

Well now Cucumber-JVM (on the master branch) is using Gherkin 4.1.3, which does not allow faulty steps with both a DocString and a DataTable, so it is no longer possible to display an confusing arity missmatch exception messages for step with both a DocString and a DataTable.

Actually the code snippet in the issue that possible would need a extra branch in a nested if statement has been change to (https://github.com/cucumber/cucumber-jvm/blob/master/core/src/main/java/cucumber/runtime/StepDefinitionMatch.java#L61-L63):

        if (!step.getArgument().isEmpty()) {
            argumentCount++;
        }

where step is an instance of gherkin.pickles.PickleStep.

lock commented

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.