背景

数据驱动是我们写自动化脚本非常常用的技术,而Testng中数据驱动常用的注解是 @DataProvider,但是这个方法必须返回一个Object[][]。最近常有学生问起,如果通过外部文件作为数据源,从而实现数据驱动。 例如数据源为Excel时,如何读取excel完成数据驱动呢? 简单思路就是,读取excel数据,excel数据第一行作为map的Key其它行为值,放入map并返回。 DataProvider 注解对应方法去获取调读取excel方法,拿到返回的Object[][],其余都一样使用。
  ps.代码是不值钱的,关键是解决问题的思路。

Demo

话不多说,直接上Demo。

1.准备Excel数据

读取Excel,通过Testng完成数据驱动 - 图1

  1. 新建maven工程,并导入 poi相关包:
  1. <dependency>
  2. <groupId>org.apache.poi</groupId>
  3. <artifactId>poi-ooxml</artifactId>
  4. <version>3.15</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.apache.poi</groupId>
  8. <artifactId>poi</artifactId>
  9. <version>3.15</version>
  10. </dependency>

3.读取Excel数据,并放入Map中返回。

  1. /**
  2. * @param file 读取某个excel文件
  3. * @return Object
  4. */
  5. public Object[][] testData(String file) {
  6. ArrayList<String> arrkey = new ArrayList<String>();
  7. Workbook workbook = WorkBookEhi.getWorkbook(file);
  8. Sheet sheet = workbook.getSheetAt(0);
  9. // 获取总行数
  10. int rowTotalNum = sheet.getLastRowNum()+1;
  11. // 总列数
  12. int columns = sheet.getRow(0).getPhysicalNumberOfCells();
  13. HashMap<String, String>[][] map = new HashMap[rowTotalNum - 1][1];
  14. // 对数组中所有元素hashmap进行初始化
  15. if (rowTotalNum > 1) {
  16. for (int i = 0; i < rowTotalNum - 1; i++) {
  17. map[i][0] = new HashMap();
  18. }
  19. } else {
  20. log.error("测试的Excel" + file + "中没有数据");
  21. }
  22. // 获得首行的列名,作为hashmap的key值
  23. for (int c = 0; c < columns; c++) {
  24. String cellvalue = CellUnit.getCellValue(sheet, 0, c);
  25. arrkey.add(cellvalue);
  26. }
  27. // 遍历所有的单元格的值添加到hashmap中
  28. for (int r = 1; r < rowTotalNum; r++) {
  29. for (int c = 0; c < columns; c++) {
  30. String cellvalue = CellUnit.getCellValue(sheet, r, c);
  31. map[r - 1][0].put(arrkey.get(c), cellvalue);
  32. }
  33. }
  34. return map;
  35. }

当然这个这里面的getWorkbook()方法我也是经过封装了,代码如下:

  1. /**
  2. * 创建 workbook
  3. *
  4. * @param filePath excel文件路径
  5. * @return Workbook 对象
  6. * @throws IOException
  7. */
  8. public static Workbook getWorkbook(String filePath) {
  9. Workbook wb = null;
  10. try {
  11. if (filePath.endsWith(".xls")) {
  12. File file = new File(filePath);
  13. InputStream is = new FileInputStream(file);
  14. wb = new HSSFWorkbook(is);
  15. } else if (filePath.endsWith(".xlsx") || filePath.endsWith(".xlsm")) {
  16. wb = new XSSFWorkbook(filePath);
  17. }
  18. } catch (IOException e) {
  19. e.printStackTrace();
  20. }
  21. return wb;
  22. }
  1. CellUnit.getCellValue()方法封装如下:
  1. /**
  2. * 通过sheet 行号和列返回值
  3. *
  4. * @param sheet sheet name
  5. * @param rowNum 行号
  6. * @param cellNum 列号
  7. * @return
  8. */
  9. public static String getCellValue(Sheet sheet, int rowNum, int cellNum) {
  10. Cell cell = sheet.getRow(rowNum).getCell(cellNum);
  11. String value = CellUnit.getCellValue(cell);
  12. return value;
  13. }
  14. CellUnit.getCellValue() 方法封装如下:
  15. /**
  16. * 把不同类型的单元格转换成字符串,并返回
  17. *
  18. * @param cell cell
  19. * @return 当个单元格值
  20. */
  21. public static String getCellValue2(Cell cell) {
  22. String value = "";
  23. switch (cell.getCellTypeEnum()) {
  24. case STRING:
  25. value = String.valueOf(cell.getRichStringCellValue());
  26. return value;
  27. case NUMERIC:
  28. value = String.valueOf(cell.getNumericCellValue());
  29. return value;
  30. case BOOLEAN:
  31. value = String.valueOf(cell.getBooleanCellValue());
  32. return value;
  33. case FORMULA:
  34. value = String.valueOf(cell.getCellFormula());
  35. return value;
  36. case ERROR:
  37. value = String.valueOf(cell.getErrorCellValue());
  38. return value;
  39. case BLANK:
  40. return value;
  41. default:
  42. log.warn("未知该单元格类型");
  43. return value;
  44. }
  45. }

4.Testng 使用数据

  1. @DataProvider(name = "testData")
  2. public Object[][] data() {
  3. TestCaseExcel testcase = new TestCaseExcel();
  4. return testcase.testData(file);
  5. }
  6. @Test(dataProvider = "testData")
  7. public void testCase(HashMap<String, String> data) {
  8. String fileName = data.get("excelName");
  9. String bpSheetName = data.get("Benefits Package Sheet");
  10. int bpRowNum = Integer.parseInt(data.get("BP sheet RowNum"));
  11. String csvSheetName = data.get("Cost Share Variances Sheet");
  12. int csvRowNum = Integer.parseInt(data.get("CSV Sheet RowNum"));
  13. String hiosPlanID = data.get("HIOS Plan ID");
  14. String isPass = data.get("isPass");