使用 TestNG 和 Excel 进行数据驱动测试
使用 TestNG 和 Excel 进行数据驱动测试,测试完成后将测试结果写入Excel的数据文件最后一列。
在D盘下,编辑“测试数据.xlsx”文件(注意扩展名必须是 .xlsx),编辑的文件内容如图所示:
其中第1列为序号,第2列为测试用例名称,第3~6列是使用,测试数据,第7~9列是使用的测试数据,第10列表示此数据行是否需要在testing里面执行(y表示执行,n表示不执行),第11列显示测试执行的结果是否正确(在测试执行前将此列内容均填写为“/”,表示测试用例未被执行,执行成功后则会显示测试成功或者测试失败)
ExcelUtil 类代码如下:
package cn.hx.util; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Row; // 本类主要实现文件扩展名为.xlsx的Excel文件操作 public class ExcelUtil { private static XSSFSheet ExcelWSheet; private static XSSFWorkbook ExcelWBook; private static XSSFCell Cell; private static XSSFRow Row; // 设定要操作Excel的文件路径和Excel文件中的sheet名称 // 在读/写Excel的时候,均需要先调用此方法,设定要操作的Excel文件路径和要操作的Sheet名称 public static void setExcelFile(String filePath, String fileName, String sheetName) throws Exception { FileInputStream ExcelFile; try { // 实例化Excel文件的FileInputStream对象 ExcelFile = new FileInputStream(filePath+"/"+fileName); // 实例化Excel文件的XSSFWorkbook对象 ExcelWBook = new XSSFWorkbook(ExcelFile); // 实例化XSSFSheet对象,指定Excel文件中的sheet名称,后续用于sheet中行、列和单元格的操作 ExcelWSheet = ExcelWBook.getSheet(sheetName); } catch (Exception e) { throw (e); } } // 读取Excel文件制定单元格的函数,只支持扩展名为.xlsx的Excel文件 public static String getCellData(int RowNum, int ColNum) { try { // 通过函数参数指定单元格的行号和列号,获取指定的单元格对象 Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum); @SuppressWarnings("deprecation") String CellData = Cell.getCellType() == XSSFCell.CELL_TYPE_STRING ? Cell.getStringCellValue() + "" : String.valueOf(Math.round(Cell.getNumericCellValue())); return CellData; } catch (Exception e) { return ""; } } // 在Excel文件的执行单元格中写入数据,只支持扩展名为.xlsx的Excel文件 public static void setCellData(int RowNum, int ColNum, String Result) throws Exception { try { // 获取Excel文件中的行对象 Row = ExcelWSheet.getRow(RowNum); // 如果单元格为空,则返回Null Cell = Row.getCell(ColNum, Row.RETURN_BLANK_AS_NULL); if (Cell == null) { // 当单元格的对象是Null时,则创建单元格 // 如果单元格为空,无法直接调用单元格对象的setCellValue方法设定单元格的值 Cell = Row.createCell(ColNum); // 创建单元格后可以调用单元格对象的setCellValue方法设定单元格的值 Cell.setCellValue(Result); } else { // 单元格中有内容,则可以直接调用单元格对象的setCellValue方法设定单元格的值 Cell.setCellValue(Result); } // 实例化写入Excel文件的文件输出流对象 FileOutputStream fileOut = new FileOutputStream(Constant.FilePath+"/"+Constant.FileName); // 后续再改 // 将内容写入Excel文件中 ExcelWBook.write(fileOut); // 调用flush方法强制刷新写入文件 fileOut.flush(); // 关闭文件输出流对象 fileOut.close(); } catch (Exception e) { throw (e); } } // 从Excel文件获取测试数据的静态方法 @SuppressWarnings("deprecation") public static Object[][] getTestData(String filePath, String fileName, String sheetName) throws IOException { // 根据参数传入的数据文件路径和文件名称,组合出Excel数据文件的绝对路径 File file = new File(filePath + "/" + fileName); // 创建FileInputStream对象用于读取Excel文件 FileInputStream inputStream = new FileInputStream(file); // 声明Workbook对象 Workbook workbook = null; // 获取文件名参数的扩展名,判断是.xlsx文件还是.xls文件 String fileExtensionName = fileName.substring(fileName.indexOf(".")); // 判断文件类型如果是.xlsx,则使用XSSFWorkbook对象进行实例化 // 判断文件类型如果是.xls,则使用SSFWorkbook对象进行实例化 if (fileExtensionName.equalsIgnoreCase(".xlsx")) { workbook = new XSSFWorkbook(inputStream); } else if (fileExtensionName.equalsIgnoreCase(".xls")) { workbook = new HSSFWorkbook(inputStream); } // 通过sheetName参数生成Sheet对象 Sheet sheet = workbook.getSheet(sheetName); // 获取Excel数据文件Sheet1中数据的行数,getLastRowNum方法获取数据的最后行号 // getFirstRowNum方法数据第一行行号,相减之后算出数据的行数 // 注意:Excel文件的行号和列号都是从0开始的 int rowCount = sheet.getLastRowNum() - sheet.getFirstRowNum(); // 创建名为records的list对象来存储从Excel数据文件读取的数据 List<Object[]> records = new ArrayList<>(); // 使用两个for循环遍历Excel数据文件的所有数据(除了第一行,第一行是数据列名称),所以i从1开始 for (int i = 1; i < rowCount + 1; i++) { // 使用getRow方法获取行对象 Row row = sheet.getRow(i); /* * 声明一个数组,用来存储Excel数据文件每行中的测试用例和数据,数组的大小用getLastCellNum-2来进行动态声明, * 实现测试数据个数和数组大小一致,因为Excel数据文件中的测试数据行的最后一个单元格为测试执行结果,倒数第二个单元格 * 为测试数据是否执行的状态位,所以最后两列的单元格数据并不需要传入测试方法中,所以使用getLastCellNum-2去掉 * 每行中的最后两个单元格数据,计算所要存储的测试数据个数,并做为测试数组的初始化大小 */ Object fields[] = new Object[row.getLastCellNum() - 2]; // if用于判断测试数据是否要参与测试执行,Excel文件的倒数第二列为数据行的状态位,y执行,n跳过 if (row.getCell(row.getLastCellNum() - 2).getStringCellValue().equals("y")) { for (int j = 0; j < row.getLastCellNum() - 2; j++) { // 判断Excel的单元格字段使数字还是字符,字符串格式调用getStringCellValue方法获取 // 数字格式调用getNumericCellValue方法获取 fields[j] = (row.getCell(j).getCellType() == XSSFCell.CELL_TYPE_STRING
? row.getCell(j).getStringCellValue()
: String.valueOf(Math.round(row.getCell(j).getNumericCellValue()))); } // fields的数据对象存储到records的list当中 records.add(fields); } } // 定义函数返回值,即Object[][],将存储测试数据的list转换为一个Object二维数组 Object[][] results = new Object[records.size()][]; for (int i = 0; i < records.size(); i++) { results[i] = records.get(i); } return results; } public static int getLastColumnNum() { // 返回数据最后一列的列号,如果有12列,则返回11 return ExcelWSheet.getRow(0).getLastCellNum() - 1; } }
TestNG 获取测试数据执行测试类,代码如下:
package cn.hx.testScripts; import java.io.IOException; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import cn.hx.appModules.BandWideTest; import cn.hx.appModules.BeforeLineLogin_Action; import cn.hx.appModules.LineLogin; import cn.hx.appModules.SelectTestType_Action; import cn.hx.util.Constant; import cn.hx.util.ExcelUtil; import cn.hx.util.Log; import cn.hx.util.SelectBrowser; import junit.framework.Assert; @SuppressWarnings("deprecation") public class AutoLoginPublicSpTst { // 定义dataProvider,并命名为testData @DataProvider(name = "testData") public static Object[][] data() throws IOException { /* * 调用ExcelUtil类中的getTestData静态方法,获取Excel数据文件中倒数第二列标记为"y"的测试数据行, * 函数参数为常量Constant.TestDataExcelFilePath和常量Constant. * TestDataExcelFileSheet,指定数据文件的路径和Sheet名称 */ return ExcelUtil.getTestData(Constant.FilePath, Constant.FileName, Constant.TestDataExcelFileSheet); } @Test(dataProvider = "testData") public void testAuthLoginPubHttp(Object caseRowNum, Object testCaseName, Object browser, Object lineLoginType, Object testType, Object selectTestType, Object assWord1, Object assWord2, Object assWord3) throws Exception { Log.startTestCase((String) testCaseName); Log.info("启动WebDriver"); Log.info("调用 SelectBrowser 类的 browserSelect 方法,启动 " + (String) browser + " 浏览器"); // chrome--谷歌浏览器,firefox--火狐浏览器,ie--IE浏览器 SelectBrowser.browserSelect(browser); Log.info("调用 BeforeLineLogin_Action 类的 execute 方法"); Log.info("断言线路登录页面是否含关键字“"+assWord1+"”"); try { BeforeLineLogin_Action.execute(SelectBrowser.driver, assWord1); } catch (AssertionError error) { Log.info("进入线路登录页面失败"); ExcelUtil.setCellData(Integer.parseInt((caseRowNum.toString()).split("[.]")[0]), ExcelUtil.getLastColumnNum(), "执行失败"); Assert.fail("执行 BeforeLineLogin_Action 类的 execute 方法失败"); } Log.info("调用 LineLogin 类的 lineLogin_Action 方法"); Log.info("断言选择测速项目类型页面是否含关键字“"+assWord2+"”"); try { // manual--手动登录,automatic--自动登录 // family--家庭用户,group--集团用户,other--其他用户 LineLogin.lineLogin_Action(SelectBrowser.driver, lineLoginType, "", assWord2); } catch (AssertionError error) { Log.info("进入选择测速项目类型页面失败"); ExcelUtil.setCellData(Integer.parseInt((caseRowNum.toString()).split("[.]")[0]), ExcelUtil.getLastColumnNum(), "执行失败"); Assert.fail("执行 LineLogin 类的 lineLogin_Action 方法失败"); } Log.info("调用 SelectTestType_Action 类的 testTypeSelect 方法"); Log.info("断言测速页面是否含关键字“"+assWord3+"”"); try { // bandWidth--宽带测速,surfExp--上网体验,lineMan--线务员测速 SelectTestType_Action.testTypeSelect(SelectBrowser.driver, testType, assWord3); } catch (AssertionError error) { Log.info("进入测速页面失败"); ExcelUtil.setCellData(Integer.parseInt((caseRowNum.toString()).split("[.]")[0]), ExcelUtil.getLastColumnNum(), "执行失败"); Assert.fail("执行 SelectTestType_Action 类的 testTypeSelect 方法失败"); } Log.info("调用 BandWideTest 类的 testTypeSel_Action 方法"); BandWideTest.testTypeSel_Action(SelectBrowser.driver, selectTestType); Log.info("测速完成,在Excel的测试数据文件的“测试执行结果”列中写入“执行成功”"); ExcelUtil.setCellData(Integer.parseInt((caseRowNum.toString()).split("[.]")[0]), ExcelUtil.getLastColumnNum(), "执行成功"); Log.info("测试结果成功写入Excel数据文件的“测试执行结果”列"); Log.endTestCase((String) testCaseName); } @BeforeClass public void beforeClass() throws Exception { ExcelUtil.setExcelFile(Constant.FilePath, Constant.FileName, Constant.TestDataExcelFileSheet); } }

浙公网安备 33010602011771号