TestNG使用CSV格式DataProvider传参时如何灵活声明测试方法参数
优化TestNG DataProvider CSV参数化测试的方案
当前实现中CSV字段与测试方法入参强绑定,字段变更需要同步修改所有关联测试方法的入参列表,维护成本高。除了用String[]接收参数外,以下两种方案实用性更强:
方案1:使用Map<String,String>封装单行测试数据
原理是读取CSV的表头作为Map的key,每行数据的字段作为value,DataProvider直接返回Map对象,测试方法仅需接收一个Map参数即可,新增/删除字段不需要修改测试方法入参。
改造后的DataProvider代码
@DataProvider(name = "customer" ) public static Object[][] getUserData() throws IOException, CsvValidationException { String xlFilePath = System.getProperty("user.dir") + "/src/TestData/User.csv"; CSVReader reader = new CSVReader(new FileReader(xlFilePath)); // 读取第一行作为表头 String[] headers = reader.readNext(); List<Map<String,String>> dataList = new ArrayList<>(); String[] line; while ((line = reader.readNext()) != null) { Map<String,String> rowMap = new HashMap<>(); for(int i=0;i<headers.length;i++){ // 避免数组越界,空字段赋值为空串 rowMap.put(headers[i], i < line.length ? line[i] : ""); } dataList.add(rowMap); } // 转换成TestNG要求的二维数组 Object[][] customerData = new Object[dataList.size()][1]; for(int i=0;i<dataList.size();i++){ customerData[i][0] = dataList.get(i); } return customerData; }
测试方法示例
public void UserConsentCreate(Map<String,String> testData) throws IOException { int version = MaintreeVersion(testData.get("TestNumber")); System.out.println(version); JSONObject body =new JSONObject(); body.put("personReference",dataReader.PERSONREFERENCE_PROPERTY_READER(testData.get("TestNumber"))); body.put("contactViaEmail",testData.get("contactViaEmail")); body.put("contactViaSMS",testData.get("contactViaSMS")); body.put("mainTreeVersion",version); JSONObject auidtbody =new JSONObject(); auidtbody.put("localTime", dtf.format(now)); auidtbody.put("GMTTime", dtf.format(now)); auidtbody.put("appRequestedTime", dtf.format(now)); auidtbody.put("agentId", "1"); auidtbody.put("agentName", "App"); auidtbody.put("channel", "APP"); auidtbody.put("deviceCode","1234567890"); body.put("audit",auidtbody); // 其余业务逻辑不变 }
该方案完全和CSV字段解耦,CSV新增/删除/调整字段顺序都不需要修改方法入参,只需要在用到对应字段的地方调用get方法即可,适合字段变动频繁的场景。
方案2:自定义实体类封装测试数据
如果CSV字段相对稳定,可以定义一个和CSV字段对应的实体类,DataProvider将每行数据转换成实体类对象返回,测试方法仅需接收该实体类作为入参。
示例实体类代码
// 字段和CSV表头一一对应,可使用Lombok的@Data注解省去手写getter/setter public class UserTestData { private String TestNumber; private String email; private String lastName; private String firstName; private String deviceCode; // 其余字段按CSV表头补全,添加对应的getter、setter方法 }
改造后的DataProvider核心逻辑
@DataProvider(name = "customer" ) public static Object[][] getUserData() throws IOException, CsvValidationException { String xlFilePath = System.getProperty("user.dir") + "/src/TestData/User.csv"; CSVReader reader = new CSVReader(new FileReader(xlFilePath)); reader.readNext(); // 跳过表头 List<UserTestData> dataList = new ArrayList<>(); String[] line; // 也可直接用OpenCSV等库直接映射到实体类,省去手动赋值逻辑 while ((line = reader.readNext()) != null) { UserTestData userData = new UserTestData(); userData.setTestNumber(line[0]); userData.setEmail(line[1]); userData.setLastName(line[2]); // 其余字段按顺序赋值 dataList.add(userData); } Object[][] customerData = new Object[dataList.size()][1]; for(int i=0;i<dataList.size();i++){ customerData[i][0] = dataList.get(i); } return customerData; }
测试方法示例
public void UserConsentCreate(UserTestData testData) throws IOException { int version = MaintreeVersion(testData.getTestNumber()); System.out.println(version); JSONObject body =new JSONObject(); body.put("personReference",dataReader.PERSONREFERENCE_PROPERTY_READER(testData.getTestNumber())); body.put("contactViaEmail",testData.getContactViaEmail()); body.put("contactViaSMS",testData.getContactViaSMS()); body.put("mainTreeVersion",version); // 其余业务逻辑不变 }
该方案有类型校验,IDE可以自动补全属性,不会出现写错字段名的问题,代码可读性更高,适合字段稳定的长期维护项目。
内容的提问来源于stack exchange,提问作者lahiru dilruwan
相关产品推荐
相关产品推荐

