背景
自動化測試過程中,數據驅動這一環節是無法避免的。爲了降低後期的維護成本,數據驅動是一個有效的解決方案。TestNG中常用的數據驅動註解是 @DataProvider ,該方法返回一個Object[][]。
實踐
簡單的數據驅動
舉個例子:一個簡單的登錄接口,大致代碼如下:
public class Login {
public static boolean isLogin = false;
/**
* 模擬登陸校驗方法
* @param name 用戶名
* @param pwd 密碼
* @return 登陸返回信息
*/
public String userLogin(String name,String pwd){
if(name == null || name.equals("") || pwd ==null || pwd.equals("")){
System.out.println("用戶名或密碼爲空");
isLogin = false;
return "用戶名或密碼不能爲空";
}else if (name == "admin" || name.equals("admin")){
System.out.println("管理員");
isLogin = true;
return "歡迎管理員";
}else{
System.out.println("正常用戶");
isLogin = true;
return "歡迎"+name;
}
}
public static void main(String[] args){
Login login = new Login();
login.userLogin("","");
}
}
爲了測試這個接口,我們大致準備瞭如下用例:
用戶名 | 密碼 | 期望結果 |
---|---|---|
" " | " " | 用戶名或密碼不能爲空 |
admin | " " | 用戶名或密碼不能爲空 |
wade | " " | 用戶名或密碼不能爲空 |
wade | 123 | 歡迎wade |
admin | 123 | 歡迎管理員 |
" " | 123 | 用戶名或密碼不能爲空 |
簡單的實現數據驅動方法:
新建一個Loginparams.java
public class LoginParams {
/**
* 提供用戶登陸測試方法數據
* @return
*/
@DataProvider
public Object[][] getUsers(){
return new Object[][]{
{"zhangsan","123456","歡迎zhangsan"},
{"lisi","","用戶名或密碼不能爲空"},
{"","","用戶名或密碼不能爲空"},
{"admin","123456","歡迎管理員"}
};
}
在測試用例中
public class LoginTest {
@Test(dataProvider = "getUsers", dataProviderClass = LoginParams.class)
public void testLogin(String name1, String pwd1, String expect1){
Login login = new Login();
String ac = login.userLogin(name1,pwd1);
Assert.assertEquals(ac,expect1);
}
}
運行結果如下:
利用外部數據源
常見的外部數據源,一般講數據存在db中,卸載xml/txt/yaml/excel中等等。
這邊以excel爲例,讀取excel中的數據。
大致思路:
先用POI讀取excel。解析讀取數據,返回list,返回Object[][]即可
備註:這邊主要參考了Refain的文章,有興趣可以去原博看看
主要代碼如下:
public class ReadExcelUtil {
/**
* read excel
* @param
* @return
*/
public static List<Map<String, String>> getExcuteList(String filePath) {
Workbook wb = null;
Sheet sheet = null;
Row row = null;
List<Map<String, String>> list = null;
String cellData = null;
String columns[] = {"name", "pwd", "exp","pro","num","res"};
wb = readExcel(filePath);
if (wb != null) {
//用來存放表中數據
list = new ArrayList<Map<String, String>>();
sheet = wb.getSheetAt(0);
int rownum = sheet.getPhysicalNumberOfRows();
row = sheet.getRow(0);
int colnum = row.getPhysicalNumberOfCells();
for (int i = 1; i < rownum; i++) {
Map<String, String> map = new LinkedHashMap<String, String>();
row = sheet.getRow(i);
if (row != null) {
for (int j = 0; j < colnum; j++) {
cellData = (String) getCellFormatValue(row.getCell(j));
map.put(columns[j], cellData);
}
} else {
break;
}
list.add(map);
}
}
return list;
}
/**
* 判斷excel文件的類型
*
* @param filePath
* @return
*/
public static Workbook readExcel(String filePath) {
Workbook wb = null;
if (filePath == null) {
return null;
}
String extString = filePath.substring(filePath.lastIndexOf("."));
InputStream is = null;
try {
is = new FileInputStream(filePath);
if (".xls".equals(extString)) {
return wb = new HSSFWorkbook(is);
} else if (".xlsx".equals(extString)) {
return wb = new XSSFWorkbook(is);
} else {
return wb = null;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return wb;
}
public static Object getCellFormatValue(Cell cell) {
Object cellValue = null;
if (cell != null) {
//判斷cell類型
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC: {
cellValue = String.valueOf(cell.getNumericCellValue());
break;
}
case Cell.CELL_TYPE_FORMULA: {
//判斷cell是否爲日期格式
if (DateUtil.isCellDateFormatted(cell)) {
//轉換爲日期格式YYYY-mm-dd
cellValue = cell.getDateCellValue();
} else {
//數字
cellValue = String.valueOf(cell.getNumericCellValue());
}
break;
}
case Cell.CELL_TYPE_STRING: {
cellValue = cell.getRichStringCellValue().getString();
break;
}
default:
cellValue = "";
}
} else {
cellValue = "";
}
return cellValue;
}
在Loginparams.java文件中,數據驅動這樣實現
@DataProvider
public Object[][] dataMethod(){
List<Map<String, String>> result = ReadExcelUtil.getExcuteList("E:\\Xunit\\src\\test\\java\\LoginData\\bug.xlsx");
Object[][] files = new Object[result.size()][];
for(int i=0; i<result.size(); i++){
files[i] = new Object[]{result.get(i)};
}
return files;
}
測試一下:
@Test(dataProvider = "dataMethod",dataProviderClass = LoginParams.class)
public void testBuy2(HashMap<String,String> data){
System.out.println(data.get("name")+data.get("pwd"));
String s = login.userLogin(data.get("name"),data.get("pwd"));
Assert.assertEquals(s,data.get("exp"));
int pro = Integer.parseInt(data.get("pro").substring(0,(data.get("pro").length()-2)));
int buynum = Integer.parseInt(data.get("num").substring(0,(data.get("num").length()-2)));
int res = shopping.buys(pro,buynum);
int exp = Integer.parseInt(data.get("res").substring(0,(data.get("res").length()-2)));
Assert.assertEquals(res,exp);
}
由於返回的結果是string類型,而且後面帶小數點,所以這邊加了自動截取後兩位
最終運行結果如下: