Search code examples
javacucumber

Cucumber datatable parameter: How to automatically apply custom method to all cells' data?


I would like to apply a custom method to any cell of a datatable without having to explicitly do so in the glue step code for each cell manually. My scenarios can have 1 to n columns so I cannot use a 'mapping' class with corresponding properties, AND the phrase may be something totally different as well but still with a datatable that needs its cells' data to be converted automatically.

Note: obviously the idea behind the custom method is not as simple as replacing "_" with " " that could be done in the glue file straight away, it has much more complex logic behind which cannot be done in the static feature file itself.

Consider a feature file with a scenario such as:

  Scenario: Verify datatable cell transformation
    Then Verify default datatable cells automatic converter:
    | row_1_cell_1_value | row_1_cell_2_value | row_1_cell_3_value |
    | row_2_cell_1_value | row_2_cell_2_value | row_2_cell_3_value |

And the glue file with the corresponding method:

@Then("Verify default datatable cells automatic converter:")
public void VerifyDatatableCellsAutomaticConverter(DataTable datatable)
{
    System.out.println("datatable.row(0).get(0) = '" + datatable.row(0).get(0) + "'");
}

Output would be:

datatable.row(0).get(0) = 'row_1_cell_1_value'

I would like to perform a call to a custom method on every cell of the datable, without an explicit call in the glue method itself because I need to do it for every scenario. I tried some code with the @DefaultParameterTransformer, @DefaultDataTableEntryTransformer and @DefaultDataTableCellTransformer in my ParameterTypes class, but if I do any output, nothing is ever printed out.

Let's imagine my 'customMethod' would replace all "_" characters with " " of the cells of the datable; how can I achieve the same as:

@Then("Verify default datatable cells automatic converter:")
public void VerifyDatatableCellsAutomaticConverter(DataTable datatable)
{
    // Pseudo code to make it shorter
    DataTable datatable = foreachrows(i).foreachcells(j){ customMethod(datatable.row(i).get(j)); }
    System.out.println("datatable.row(0).get(0) = '" + datatable.row(0).get(0) + "'");
    System.out.println("datatable.row(0).get(1) = '" + datatable.row(0).get(1) + "'");
    // etc.
    System.out.println("datatable.row(1).get(2) = '" + datatable.row(1).get(2) + "'");
}

Output would be:

datatable.row(0).get(0) = 'row 1 cell 1 value' datatable.row(0).get(1) = 'row 1 cell 2 value' ... datatable.row(1).get(2) = 'row 2 cell 3 value'

Something such as:

public class ParameterTypes
{
    @DefaultParameterTransformer
    @DefaultDataTableEntryTransformer
    @DefaultDataTableCellTransformer
    public Object transformer(Object fromValue, Type toValueType)
    {
        System.out.println("fromValue = '" + fromValue.toString());
        return "";
    }
}

Would not even output the line as if the method was not actually used.

How can I do this ? Additionally, could it also be possible to do for the Examples datatable when the scenario is with the Outline keyword ?

Thank you

PS: I use <cucumber.version>7.11.1</cucumber.version>


Solution

  • You need to transform the data table into something for the transformation to be invoked. You could implement your own table like object that has variabele with and height.

        @DataTableType
        public MyTranformedTable transformAndLog(DataTable table 
    
    ) {
            // Do logging and transformation here
            return new MyTranformedTable(table);
        }
    

    Then use MyTranformedTable as the argument for your step definitions.

    Additionally, could it also be possible to do for the Examples datatable when the scenario is with the Outline keyword ?

    Example tables are syntactic sugar for repeating the scenario.

    So only with a parameter type. You'd have to declare this in your step definitions. E.g. @Given("My {transformedString}").