在关键字驱动测试框架的基础上,部分使用数据驱动测试框架,例如:
如果在测试用例中有使用数据驱动,即在测试用例的“测试数据”列填写其数据源Sheet名称,如Templates。
在Templates中,邮件主题列是测试数据,其对应的是A列。
在测试用例VerifyCards的测试步骤中,将使用数据驱动的步骤的操作值用A表示
接下来更改ExcelUtil.java
package cn.summer.util;
import java.io.FileInputStream;
import java.io.FileOutputStream;
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 cn.summer.testScripts.TestSuiteByExcel;
//本类主要实现扩展名为“.xlsx”的Excel文件操作
public class ExcelUtil {
private static XSSFSheet ExcelWSheet;
private static XSSFWorkbook ExcelWBook;
private static XSSFCell Cell;
private static XSSFRow Row;
//设定要操作的Excel文件的路径
//在读/写Excel文件的时候,需要先设定要操作的Excel文件路径
public static void setExcelFile(String Path)
{
FileInputStream ExcelFile;
try {
//实例化Excel文件的FileInputStream对象
ExcelFile = new FileInputStream(Path);
//实例化Excel文件的XSSFWorkbook对象
ExcelWBook = new XSSFWorkbook(ExcelFile);
}catch(Exception e) {
TestSuiteByExcel.testResult = false;
System.out.println("Excel路径设定失败");
e.printStackTrace();
}
}
//设定要操作的Excel文件的路径和Excel文件中的Sheet名称
//在读/写Excel文件的时候,设定要操作的Excel文件路径和要操作的Sheet名称
public static void setExcelFile(String Path, String SheetName)
{
FileInputStream ExcelFile;
try {
//实例化Excel文件的FileInputStream对象
ExcelFile = new FileInputStream(Path);
//实例化Excel文件的XSSFWorkbook对象
ExcelWBook = new XSSFWorkbook(ExcelFile);
//实例化Sheet对象,指定Excel文件的Sheet名称,后续用于对Sheet中行、列和单元格的操作
ExcelWSheet = ExcelWBook.getSheet(SheetName);
}catch(Exception e) {
TestSuiteByExcel.testResult = false;
System.out.println("Excel路径设定失败");
e.printStackTrace();
}
}
//读取Excel文件,通过列字母获取列索引
public static int excelColStrToNum(String colStr) {
int num = 0;
int result = 0;
char ch = colStr.charAt(0);
num = (int)(ch-'A');
result += num;
return result;
}
//读取Excel文件指定单元格的函数,此函数只支持扩展名为“.xlsx”的Excel文件
public static String getCellData(String SheetName, int RowNum, int ColNum){
ExcelWSheet = ExcelWBook.getSheet(SheetName);
try {
//通过函数参数指定单元格的行号和列号,获取指定的单元格对象
Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
//如果单元格的内容为字符串类型,则使用getStringCellValue方法
//如果单元格的内容为数字类型,则使用getNumericCellValue方法
String CellData = Cell.getCellType()==XSSFCell.CELL_TYPE_STRING ?
Cell.getStringCellValue() + ""
:String.valueOf(Math.round(Cell.getNumericCellValue()));
//函数返回指定单元格的字符串内容
return CellData;
}catch(Exception e) {
TestSuiteByExcel.testResult = false;
e.printStackTrace();
//如果读取遇到异常,则返回空字符串
return "";
}
}
//获取Excel文件中最后一行的列号
//public static int getlastColumnNum() {
//函数返回Sheet中最后一行的列号
//return ExcelWSheet.getRow(0).getLastCellNum()-1;
//}
//获取Excel文件中最后一行的行号
public static int getLastRowNum() {
//函数返回Sheet中最后一行的行号
return ExcelWSheet.getLastRowNum();
}
//获取指定Sheet中的数据总行数
public static int getRowCount(String SheetName) {
ExcelWSheet = ExcelWBook.getSheet(SheetName);
int number = ExcelWSheet.getLastRowNum();
return number;
}
//在Excel的指定Sheet中,获取第一次包含指定测试用例序号的行号
public static int getFirstRowContainsTestCaseID(String sheetName,
String testCaseName, int colNum){
int i;
try {
ExcelWSheet = ExcelWBook.getSheet(sheetName);
int rowCount = ExcelUtil.getRowCount(sheetName);
//使用循环的方法遍历测试用例序号列的所有行,判断是否包含某个测试用例序号关键字
for(i = 0; i<rowCount; i++) {
//如果包含,则退出for循环,并返回包含测试用例序号关键字的行号
if(ExcelUtil.getCellData(sheetName, i, colNum).equalsIgnoreCase
(testCaseName)) {
break;
}
}
return i;
}catch(Exception e) {
TestSuiteByExcel.testResult = false;
return 0;
}
}
//获取指定Sheet中某个测试用例步骤的个数
public static int getTestCaseLastStepRow(String SheetName,
String testCaseID, int testCaseStartRowNumber){
try {
ExcelWSheet = ExcelWBook.getSheet(SheetName);
/*从包含的测试用例序号的第一行开始逐行遍历,知道某一行不出现指定测试用例序号
*此时的遍历次数就是次测试用例步骤的个数
*/
for(int i = testCaseStartRowNumber; i<=ExcelUtil.
getRowCount(SheetName)-1; i++) {
if(!testCaseID.equals(ExcelUtil.getCellData(SheetName,i,
Constant.Col_TestCase_ID))) {
int number = i;
return number;
}
}
int number = ExcelWSheet.getLastRowNum()+1;
return number;
}catch(Exception e) {
TestSuiteByExcel.testResult = false;
return 0;
}
}
//在Excel文件的执行单元格中写入数据,此函数只支持扩展名为".xlsx"的Excel文件
@SuppressWarnings("static-access")
public static void setCellData(String SheetName, int RowNum, int ColNum,
String Result){
ExcelWSheet = ExcelWBook.getSheet(SheetName);
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
.Excel_FilePath);
//将内容写入Excel文件
ExcelWBook.write(fileOut);
//调用flush方法强制刷新写入文件
fileOut.flush();
//关闭文件输出流对象
fileOut.close();
}catch(Exception e) {
TestSuiteByExcel.testResult = false;
e.printStackTrace();
}
}
}
更改Constant.java
package cn.summer.util;
public class Constant {
//工程包、包名、上一级包名
public static String projectDir;
public static String packageName;
public static String packageParentDir;
//获取当前文件所在目录的父目录的绝对路径
public static String parentDirPath = getParentPath();
//测试用例及数据相关常量设定
//Excel文件路径
public static String Excel_FilePath = parentDirPath+"\\data\\混合驱动测试用例.xlsx";
//objectMap.properties配置文件所在路径
public static String ObjectMap_FilePath = parentDirPath+"\\data\\objectMap.properties";
//"TestSuite" sheet中的列号常量设定
//"TestSuite" Sheet名称
public static final String Sheet_TestSuite_Name = "TestSuite";
//第1列用0表示,为测试用例名称列
public static final int Col_TestCase_ID = 0;
//第4列用3表示,为是否运行列
public static final int Col_TestCase_RunFlag = 3;
//第5列用4表示,为测试数据列
public static final int Col_DateSource_SheetName = 4;
//第6列用5表示,为测试结果列
public static final int Col_TestCase_TestResult = 5;
//测试步骤Sheet的列号常量设定
//第4列用3表示,为关键字列
public static final int Col_KeyWordsAction = 3;
//第5列用4表示,为操作元素的定位表达式列
public static final int Col_LocatorExpression = 4;
//第6列用5表示,为操作值列
public static final int Col_OperateVaule = 5;
//第7列用6表示,为是否运行列
public static final int Col_TestStep_RunFlag = 6;
//第8列用7表示,为测试结果列
public static final int Col_TestStep_TestResult = 7;
//数据驱动Sheet中的列号常量设定
//第2列用1表示,为是否执行
public static final int Col_DataSource_RunFlag = 1;
//第3列用2表示,为测试执行结果列
public static final int Col_DataSource_TestResult = 2;
//获取所在目录的父目录的绝对路径方法
public static String getParentPath() {
//获取工程路径
projectDir = System.getProperty("user.dir")+"\\src";
//获取类所在包名
packageName = Constant.class.getPackage().getName();
//获取类所在包的上一级包名
packageParentDir = packageName.substring(0,packageName.lastIndexOf("."));
//格式化包名为路径名
packageParentDir = String.format("/%s/",packageParentDir.contains(".")?
packageParentDir.replaceAll("\\.","/"):packageParentDir);
return projectDir+packageParentDir;
}
public static final String ChromeDriverPath = "D:\\CODE\\Java\\TestFramework\\Driver\\chromedriver.exe";
public static final String FirefoxDriverPath = "";
public static final String EdgeDriverPath = "";
public static final String IEDriverPath = "";
public static final String ScreenshotPath = "D:\\CODE\\Java\\TestFramework\\Screenshot\\";
}
更改TestSuiteByExcel.java
package cn.summer.testScripts;
import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.BeforeClass;
import org.apache.log4j.xml.DOMConfigurator;
import org.testng.Assert;
import org.testng.annotations.Test;
import cn.summer.configuration.KeyWordsAction;
import cn.summer.util.*;
public class TestSuiteByExcel {
public static Method method[];
public static String keyword;
public static String locatorExpression;
public static String value;
public static KeyWordsAction keyWordsaction;
public static int testStep;
public static String testData;
public static int testLastStep;
public static String testCaseID;
public static String testDataRunFlag;
public static String testCaseRunFlag;
public static String testStepRunFlag;
public static boolean testResult;
@Test
public void testTestSuite() throws Exception{
//声明一个关键动作类的实例
keyWordsaction = new KeyWordsAction();
//使用Java的反射机制获取KeyWordsAction类的所有方法对象
method = keyWordsaction.getClass().getMethods();
//定义Excel文件的路径
String excelFilePath = Constant.Excel_FilePath;
//设定读取Excel文件的"ReadEmail"Sheet为操作目标
ExcelUtil.setExcelFile(excelFilePath);
//读取“TestSuite”Sheet中的测试用例总数
int testCasesCount = ExcelUtil.getRowCount(Constant.Sheet_TestSuite_Name);
System.out.println("TestSuite表格中有 "+testCasesCount+" 行数据");
//使用for循环,执行“TestSuite”Sheet中所有标记为“y”的测试用例
for(int testCaseNo = 1; testCaseNo <= testCasesCount; testCaseNo++) {
//读取“TestSuite”Sheet中每行的测试用例序号
testCaseID = ExcelUtil.getCellData(Constant.Sheet_TestSuite_Name, testCaseNo,
Constant.Col_TestCase_ID);
//读取“TestSuite”Sheet中每行的“是否运行”列中的值
testCaseRunFlag = ExcelUtil.getCellData(Constant.Sheet_TestSuite_Name, testCaseNo,
Constant.Col_TestCase_RunFlag);
//如果“是否运行”列中的值为“y”,则执行测试用例的所有步骤
if(testCaseRunFlag.trim().equals("y")) {
//在日志中打印测试用例开始执行的信息
Log.startTestCase(testCaseID);
//设定测试用例的当前结果为“true”,表明测试用例执行成功
testResult = true;
//在测试步骤Sheet(如“ReadMail01”)中,
//获取当前要执行测试用例的第一个步骤所在行的行号
testStep = ExcelUtil.getFirstRowContainsTestCaseID(
testCaseID, testCaseID, Constant.Col_TestCase_ID);
//在“ReadMail01”Sheet中,获得当前要执行测试用例的最后一个步骤,所在行的行号
testLastStep = ExcelUtil.getTestCaseLastStepRow(
testCaseID, testCaseID, testStep);
//读取“TestSuite”Sheet中的测试数据列内容
testData = ExcelUtil.getCellData(Constant.Sheet_TestSuite_Name,
testCaseNo, Constant.Col_DateSource_SheetName);
//如果“TestSuite”Sheet中测试数据不为空,则运行数据驱动
if(testData.trim().equals("无")) {
Log.info("执行关键字驱动测试用例开始,Sheet表名为:"+testData);
//testResult = true;
//遍历测试步骤Sheet中的所在测试步骤
for(; testStep < testLastStep; testStep++) {
testStepRunFlag = ExcelUtil.getCellData(testCaseID,
testStep, Constant.Col_TestStep_RunFlag);
if(testStepRunFlag.trim().equals("y")) {
//从测试步骤的Sheet中读取关键字和操作值,并调用executeAction方法执行
keyword = ExcelUtil.getCellData(testCaseID,
testStep, Constant.Col_KeyWordsAction);
//在日志中打印关键字信息
Log.info("从Excel文件读取到的关键字是: "+keyword);
locatorExpression = ExcelUtil.getCellData(testCaseID,
testStep, Constant.Col_LocatorExpression);
//在日志中打印定位表达式信息
Log.info("从Excel文件读取的表达式是: "+locatorExpression);
value = ExcelUtil.getCellData(testCaseID,
testStep, Constant.Col_OperateVaule);
//在日志中打印操作值信息
Log.info("从Excel文件读取的操作值是: "+value);
executeActions(testCaseID);
if(testResult == false) {
/*如果测试用例的任何一个测试步骤执行失败,则"TestSuite"Sheet中的当前
* 执行测试用例的执行结果设定为“测试执行失败”
*/
ExcelUtil.setCellData(Constant.Sheet_TestSuite_Name,
testCaseNo, Constant.Col_TestCase_TestResult, "测试执行失败");
//在日志中打印测试用例执行完毕的信息
Log.endTestCase(testCaseID);
/*如果当前测试用例出现执行失败的情况,则将整个测试用例设定为失败状态,
* 利用break语句跳出当前的for循环,继续执行TestSuite中的下一个测试用例
*/
break;
}
if(testResult==true) {
/*
* 如果测试用例的所有步骤执行成功,则将在“TestSuite”Sheet中的当前
* 执行测试用例的执行结果设定为“测试执行成功”
*/
ExcelUtil.setCellData(Constant.Sheet_TestSuite_Name,
testCaseNo, Constant.Col_TestCase_TestResult, "测试执行成功");
}
}
}
}else {
//读取“测试数据”Sheet中的测试数据总行
int testDataCount = ExcelUtil.getRowCount(testData);
//使用for循环,执行所有标记为“y”的测试数据
for(int testDataNo = 1; testDataNo <= testDataCount; testDataNo++) {
//读取测试数据(如“OrginalEmails”)Sheet中每行的“是否运行”列中的值
testDataRunFlag = ExcelUtil.getCellData(testData, testDataNo,
Constant.Col_DataSource_RunFlag);
//如果“是否运行”列中的值为“y”,则执行该测试数据
if(testDataRunFlag.trim().equals("y")) {
Log.info("开始数据驱动用例执行...");
//testResult = true;
//遍历测试用例中的所有测试步骤
for(; testStep < testLastStep; testStep++) {
testStepRunFlag = ExcelUtil.getCellData(testCaseID,
testStep, Constant.Col_TestStep_RunFlag);
if(testStepRunFlag.trim().equals("y")) {
//从测试步骤“ReadMail01”Sheet中读取关键字和操作值,并调用executeAction方法执行
keyword = ExcelUtil.getCellData(testCaseID,
testStep,Constant.Col_KeyWordsAction);
//在日志文件中打印关键字信息
Log.info("从Excel文件读取到的关键字是: "+keyword);
locatorExpression = ExcelUtil.getCellData(testCaseID,
testStep, Constant.Col_LocatorExpression);
//在日志中打印表达式信息
Log.info("从Excel文件读取的表达式是: "+locatorExpression);
value = ExcelUtil.getCellData(testCaseID,
testStep, Constant.Col_OperateVaule);
//在日志中打印操作值信息
Log.info("从Excel文件读取的操作值是: "+value);
value = value.trim();
//若value值为“A-Z”,则替换为测试数据Sheet中的数据
if(null!=value && value.length()==1 && TestSuiteByExcel.
judgeContainsStr(value)) {
//通过Excel文件中的列字母得到索引
int conlumnNo = ExcelUtil.excelColStrToNum(value);
value = ExcelUtil.getCellData(testData,testDataNo,conlumnNo);
Log.info("Excel文件中列值为:"+value);
}
//执行用例
executeActions(testCaseID);
if(testResult==true) {
/*
* 如果当前测试步骤执行成功,在“测试数据”Sheet中,会将当前执行的
* 测试数据结果设定为“测试数据执行成功”
*/
ExcelUtil.setCellData(testData, testDataNo,
Constant.Col_DataSource_TestResult, "测试数据执行成功");
}else {
/*
* 当前测试步骤执行失败,在测试数据Sheet中,会将当前执行的测试数据
* 结果设定为“测试数据执行失败”
*/
ExcelUtil.setCellData(testData, testDataNo,
Constant.Col_DataSource_TestResult, "测试数据执行失败");
//测试步骤执行失败,则直接关闭浏览器,不再执行后续的测试
KeyWordsAction.close_browser("", "");
break;
}
}
}
/*
* 在测试步骤Sheet中,获取当前要执行测试用例
* 的第一个步骤所在行的行号
*/
testStep = ExcelUtil.getFirstRowContainsTestCaseID(
testCaseID, testCaseID, Constant.Col_TestCase_ID);
if(testResult == false) {
/*
* 如果测试用例的任何一个测试步骤执行失败,则将“TestSuite”测试用例集合
* Sheet中的当前执行测试用例的执行结果设定为“测试执行失败”
*/
ExcelUtil.setCellData(Constant.Sheet_TestSuite_Name, testCaseNo,
Constant.Col_TestCase_TestResult, "测试执行失败");
//在日志中打印测试用例执行完毕的信息
Log.endTestCase(testCaseID);
/*
* 如果当前测试用例出现执行失败的步骤,则将整个测试用例设定为失败状态,
* break语句跳出当前的for循环,继续执行TestSuite中的下一个测试用例
*/
break;
}
if(testResult == true) {
/*
* 如果当前测试用例的所有步骤执行成功,则将“TestSuite”Sheet中
* 的当前执行测试用例的执行结果设定为“测试执行成功”
*/
ExcelUtil.setCellData(Constant.Sheet_TestSuite_Name, testCaseNo,Constant.Col_TestCase_TestResult, "测试执行成功");
}
}
}
}
}
}
}
private static void executeActions(String testCaseID) {
try {
for(int i = 0;i<method.length;i++) {
//使用反射的方式,找到关键字对应的测试方法,并将value(操作值)作为测试方法的函数值进行调用
if(method[i].getName().equals(keyword)) {
method[i].invoke(keyWordsaction,locatorExpression, value);
if(testResult == true) {
/*
* 当前测试步骤执行成功,在所在Sheet中,会将当前执行的
* 测试步骤结果设定为“测试步骤执行成功”
*/
ExcelUtil.setCellData(testCaseID,
testStep, Constant.Col_TestStep_TestResult, "测试步骤执行成功");
}else {
/*
* 当前测试步骤执行失败,在所在Sheet中,会将当前执行的
* 测试步骤结果设定为“测试步骤执行失败”
*/
ExcelUtil.setCellData(testCaseID,
testStep, Constant.Col_TestStep_TestResult, "测试步骤执行失败");
//测试步骤执行失败,则直接关闭浏览器,不再执行后续的测试
KeyWordsAction.close_browser("","");
break;
}
}
}
}catch(Exception e) {
//在调用测试方法的过程中,若出现异常,则将测试设定为失败状态,停止执行测试用例
Log.info("执行出现异常,测试用例执行失败!");
Assert.fail("执行出现异常,测试用例执行失败!");
}
}
//判断str是否是A~Z之间的字符串
private static boolean judgeContainsStr(String str) {
String regex = ".*[A-Z]+.*";
Matcher matcher = Pattern.compile(regex).matcher(str);
return matcher.matches();
}
@BeforeClass
public void BeforeClass() {
//设定Log4j的配置文件为“log4j.xml"
DOMConfigurator.configure("log4j.xml");
}
}