如何自动为Cucumber数据表所有单元格应用自定义方法?
问题
需要实现Cucumber数据表所有单元格的全局自动转换,无需在每个步骤的Glue代码中手动调用自定义方法。场景列数不固定,无法使用映射类,且自定义逻辑复杂无法在feature文件中实现。尝试使用@DefaultParameterTransformer、@DefaultDataTableEntryTransformer、@DefaultDataTableCellTransformer但无效果,转换器方法未被调用。同时希望Scenario Outline的Examples数据表也能实现同样的自动转换。使用Cucumber版本7.11.1。
现有Feature示例:
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 |
现有Glue代码:
@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) + "'"); }
当前输出:
datatable.row(0).get(0) = 'row_1_cell_1_value'
期望输出(以替换下划线为空格为例):
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'
之前尝试的无效转换器代码:
public class ParameterTypes { @DefaultParameterTransformer @DefaultDataTableEntryTransformer @DefaultDataTableCellTransformer public Object transformer(Object fromValue, Type toValueType) { System.out.println("fromValue = '" + fromValue.toString() + "'"); return ""; } }
解决方案
1. 全局配置数据表单元格转换器
当步骤方法直接接收DataTable类型时,Cucumber默认不会触发单元格转换器,因为DataTable是原始数据容器。需要通过TypeRegistryConfigurer手动注册全局转换器,步骤如下:
步骤1:创建Cucumber类型配置类
实现TypeRegistryConfigurer接口,注册自定义单元格转换器:
import io.cucumber.core.api.TypeRegistry; import io.cucumber.core.api.TypeRegistryConfigurer; import io.cucumber.datatable.DataTableType; import io.cucumber.datatable.TableCellTransformer; import java.lang.reflect.Type; import java.util.Locale; public class CucumberTypeConfig implements TypeRegistryConfigurer { @Override public Locale locale() { return Locale.ENGLISH; } @Override public void configureTypeRegistry(TypeRegistry typeRegistry) { // 注册针对String类型的单元格转换器(替换为你的复杂逻辑) TableCellTransformer<String> cellTransformer = cellValue -> cellValue.replace("_", " "); typeRegistry.defineDataTableType(new DataTableType(String.class, cellTransformer)); // 注册全局默认单元格转换器,处理所有类型的单元格 typeRegistry.setDefaultDataTableCellTransformer((fromValue, toValueType) -> { if (fromValue instanceof String) { return ((String) fromValue).replace("_", " "); } return fromValue; }); } }
步骤2:修改步骤方法接收转换后的数据结构
推荐步骤方法接收List<List<String>>而非DataTable,这样转换器会自动对每个单元格生效:
import io.cucumber.java.en.Then; import java.util.List; @Then("Verify default datatable cells automatic converter:") public void verifyDatatableCellsAutomaticConverter(List<List<String>> transformedTable) { System.out.println("transformedTable.get(0).get(0) = '" + transformedTable.get(0).get(0) + "'"); System.out.println("transformedTable.get(0).get(1) = '" + transformedTable.get(0).get(1) + "'"); System.out.println("transformedTable.get(1).get(2) = '" + transformedTable.get(1).get(2) + "'"); }
运行场景后,即可得到期望的转换结果。
2. 实现Scenario Outline的Examples数据表转换
Scenario Outline中的Examples参数会被当作步骤参数处理,只需在上述配置类中添加全局参数转换器即可:
在CucumberTypeConfig的configureTypeRegistry方法中补充:
// 注册全局参数转换器,处理Scenario Outline的Examples参数 typeRegistry.setDefaultParameterTransformer((fromValue, toValueType) -> { if (fromValue instanceof String) { return ((String) fromValue).replace("_", " "); } return fromValue; });
对应的Scenario Outline示例:
Scenario Outline: Verify scenario outline examples transformation Then Verify example value: <example_cell> Examples: | example_cell | | outline_example_value |
步骤方法:
@Then("Verify example value: {string}") public void verifyExampleValue(String transformedValue) { System.out.println("transformed example value = '" + transformedValue + "'"); }
运行后输出:transformed example value = 'outline example value'
关键注意事项
- 确保
CucumberTypeConfig类在Cucumber的Glue扫描路径下 - 若必须使用
DataTable类型参数,需手动遍历单元格并应用转换逻辑,更推荐使用List<List<String>>自动触发转换器 - 转换器中的
replace("_", " ")可替换为你的复杂业务逻辑
内容的提问来源于stack exchange,提问作者user706058

