cucumber / cucumber-jvm

Cucumber for the JVM

Home Page:https://cucumber.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

List of zero elements - datatable

Raawaan opened this issue · comments

I'm trying to reuse this step def

    Then The following dials will appear
      | fieldOne    | fieldTwo|
      | 122         | true    |
      | 123         | false   |
      | 124         | true    |
      | 125         | false   |

which gets me the following list of 4 elements successfully

  @Then("The following dials will appear")
   public void theFollowingDialsWillAppear(List<TestDial> dail)  {} 

but it fails for the following.

    Then The following dials will appear
      | fieldOne    | fieldTwo|

I'm expecting a list of zero elements but I got the following stack trace

Caused by: io.cucumber.datatable.UndefinedDataTableTypeException: Can't convert DataTable to List<TestDail>.

any advice?

Could you include the full exception message please. It's important to understand exactly which branch of the transformation logic your code went into.

Please also include any (default) parameter types you've defined.

That said, I would guess you are using a default table entry transformer.

Data tables are effectively unstructured data. And Cucumber tries to guess based on the table shape and the target type how the table should be interpeted. These heuristics become inaccurate when tables with a single row or column are involved.

For example:

| a | b |

This table could represent a list containing a and b or a an empty list of beans with properties a and b. The former interpretation would suggest using the default table cell transformer, the latter the default table entry transformer.

The application of the default table entry transformer would always succeed for the empty list. This has the potential to hide errors in both the specification and implementation.

So Cucumber refuses to transform tables with a single row using the default table entry transformer.

I think the cleanest solution would be to single out the empty case with an explicit step definition. And it might even be worth making it explicit if an empty list is expected or if no list is expected.

You can of course also explicitly register data table type.

stacktrace:

Step failed
io.cucumber.core.exception.CucumberException: Could not convert arguments for step [The following dials] defined at 'com.orange.cvm.bdd.stepdefs.StepDefs(java.util.List<TestDial>)'.
It appears you did not register a data table type.
	at io.cucumber.core.runner.PickleStepDefinitionMatch.registerDataTableTypeInConfiguration(PickleStepDefinitionMatch.java:96)
	at io.cucumber.core.runner.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:50)
	at io.cucumber.core.runner.ExecutionMode$1.execute(ExecutionMode.java:10)
	at io.cucumber.core.runner.TestStep.executeStep(TestStep.java:84)
	at io.cucumber.core.runner.TestStep.run(TestStep.java:56)
	at io.cucumber.core.runner.PickleStepTestStep.run(PickleStepTestStep.java:51)
	at io.cucumber.core.runner.TestCase.run(TestCase.java:84)
	at io.cucumber.core.runner.Runner.runPickle(Runner.java:75)
	at io.cucumber.core.runtime.Runtime.lambda$executePickle$6(Runtime.java:107)
	at io.cucumber.core.runtime.CucumberExecutionContext.lambda$runTestCase$5(CucumberExecutionContext.java:137)
	at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:23)
	at io.cucumber.core.runtime.CucumberExecutionContext.runTestCase(CucumberExecutionContext.java:137)
	at io.cucumber.core.runtime.Runtime.lambda$executePickle$7(Runtime.java:107)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:235)
	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:123)
	at io.cucumber.core.runtime.Runtime.lambda$runFeatures$3(Runtime.java:89)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.SliceOps$1$1.accept(SliceOps.java:200)
	at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1602)
	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at io.cucumber.core.runtime.Runtime.runFeatures(Runtime.java:90)
	at io.cucumber.core.runtime.Runtime.lambda$run$0(Runtime.java:78)
	at io.cucumber.core.runtime.CucumberExecutionContext.lambda$runFeatures$6(CucumberExecutionContext.java:148)
	at io.cucumber.core.runtime.CucumberExecutionContext.execute(CucumberExecutionContext.java:163)
	at io.cucumber.core.runtime.CucumberExecutionContext.runFeatures(CucumberExecutionContext.java:146)
	at io.cucumber.core.runtime.Runtime.run(Runtime.java:78)
	at io.cucumber.core.cli.Main.run(Main.java:87)
	at io.cucumber.core.cli.Main.main(Main.java:30)
Caused by: io.cucumber.datatable.UndefinedDataTableTypeException: Can't convert DataTable to List<TestDial>.
Please review these problems:

I have registered data-table transformer explicitly and it's working now thank you.

   @DataTableType
    public TestDial testDialTransformer(Map<String, String> fromValue) {
        return mapper.convertValue(fromValue, TestDial.class);
    }