相信所有公司在起步自动化的时候做的都是接口自动化,为什么呢?理由很简单,接口自动化复用性强,易维护,他的产出效率要远远高于UI自动化,想想如果你的公司有成百上千的接口,每次上线都要回归,是否是一件很恐怖的事,这时我们就会针对自己的公司内部情况写一个轻量级自动化工具来完成接口回归测试。
首先,我先简述一下原理,在这里我用到了Excel2007(很抱歉这只是个Demo,没有对2003做处理,如果大家感兴趣,可以自行研究或留言),Excel是用来存储我们要测试的报文,我们每次都读取一行报文,然后设置断言,再根据断言写入测试结果,所以核心就是Excel的读写处理。
由于涉及公司业务,所以我不太方便给大家公布全部的源码,涉及报文等信息,我会以*去表示,这不会耽误大家的理解,我会分段给大家讲述每段代码的用途。
1)
public static Workbook getExcelWorkbook(String filePath) throws IOException{
Workbook book = null;
File file = null;
FileInputStream fis = null;
try {
file = new File(filePath);
if(!file.exists()){
throw new RuntimeException("文件不存在");
}else{
fis = new FileInputStream(file);
book = WorkbookFactory.create(fis);
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
} finally {
if(fis != null){
fis.close();
}
}
return book;
}
这段代码的用途就是获取我们要处理的工作簿,我们可以根据文件路径获取文件输入流,以WorkbookFactory来获取这个工作簿。
2)
public static Sheet getSheetByNum(Workbook book,int number){
Sheet sheet = null;
try {
sheet = book.getSheetAt(number);
// if(sheet == null){
// sheet = book.createSheet("Sheet"+number);
// }
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return sheet;
}
这段代码的用途是获取我们要处理的sheet,相信大家都知道Excel的sheet,那个int就是要获取的第几个,sheet的索引是默认从0开始。
3)
public static void ReadExcel(String FilePath) throws Exception {
// XSSFWorkbook book = new XSSFWorkbook(new FileInputStream(FilePath));
Workbook book = getExcelWorkbook(FilePath);
Sheet sheet = getSheetByNum(book,0);
for(int i=1;i<=sheet.getLastRowNum();i++){
// Workbook book = getExcelWorkbook(FilePath);
// Sheet sheet = getSheetByNum(book,0);
Row row = sheet.getRow(i);
ExcelBean <*> = new ExcelBean();
int lastCellNum = row.getLastCellNum();
System.out.println("逻辑列: " + lastCellNum );
Cell cell = null;
Map
for( int j = 0 ; j < lastCellNum ; j++ ){
cell = row.getCell(j);
int cellType = cell.getCellType();
System.out.println(cellType);
if(j==0){
map.put("*",getCellValue(cell,cellType) );
}else if(j==1){
map.put("*",getCellValue(cell,cellType) );
}else if(j==2){
map.put("*",getCellValue(cell,cellType) );
}else if(j==3){
map.put("*",getCellValue(cell,cellType) );
}else if(j==4){
map.put("*",getCellValue(cell,cellType));
}else if(j==5){
map.put("*",getCellValue(cell,cellType) ) ;
}else{
map.put("*",getCellValue(cell,cellType) );
}
}
test.set*((String)map.get("*"));
test.set*((String)map.get("*"));
test.set*((String)map.get("*"));
test.set*(String.valueOf(map.get("*")));
test.set*((String)map.get("*"));
test.set*((String)map.get("*"));
String header = ""+"<*>"+
"<*>"+
"<*>"+test.get*()+"<*>"+
"<*>"+test.get*()+"<*>"+
"<*>"+test.get*()+"<*>"+
"<*>"+
"<*> String body = test.get*();
String tail = "]]><*><*>";
String request = header+body+tail;
//处理报文
Client client = new Client();
String *= test.get*();
String *= test.get*();
String *= test.get*();
client.login(*, *, *);
String msg = client.rpc(request);
msg=msg.replace(",", "");
client.logout();
//断言处理
String result = getResult(msg.toString(),test.getASSERTION());
System.out.println(result);
try{
XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream(FilePath));
XSSFSheet sheet1 = wb.getSheetAt(0);
XSSFRow row1 = sheet1.getRow(i);
System.out.println("*********"+i);
XSSFCell cell1 = row1.createCell(7);
cell1.setCellValue(result);
FileOutputStream os = new FileOutputStream(FilePath);
wb.write(os);
os.close();
wb.close();
//Workbook book = getExcelWorkbook(FilePath);
}catch(Exception e){
e.printStackTrace();
}
}
}
这段代码的主要意思就是,使用双重for循环(包括行和列)遍历我们的Excel,然后呢我们创建一个Bean,这个Bean大家可以根据自己公司在请求都需要设置哪些参数来请求来自行设计,后面我会贴出Bean,如何从Excel取值,请看第4段代码,我们在取出来Excel的单元值以后,将他放入map中,通过第二个for循环的变量j来确定这个单元值对应着我们哪个报文,然后我们通过bean.set的方式将map里的值取出来,给我们的bean赋值,这里我们就获得一个完整的报文和断言等等了,然后使用test.get的方式来拼我们的报文,报文拼好后就是我们的请求了,我们请求报文,获得返回结果。
4)
public static Object getCellValue(Cell cell,int cellType){
switch (cellType) {
case Cell.CELL_TYPE_STRING: // 文本
cellValue = cell.getStringCellValue();
System.out.println(cellValue);
break;
// case Cell.CELL_TYPE_NUMERIC: // 数字、日期
//
// cellValue = cell.getNumericCellValue();
// System.out.println(cellValue);
// break;
// case Cell.CELL_TYPE_BOOLEAN: // 布尔型
// cellValue = String.valueOf(cell.getBooleanCellValue());
// System.out.println(cellValue);
// break;
// case Cell.CELL_TYPE_BLANK: // 空白
// cellValue = cell.getStringCellValue();
// System.out.println(cellValue);
// break;
// case Cell.CELL_TYPE_ERROR: // 错误
// cellValue = "错误#";
// System.out.println(cellValue);
// break;
// case Cell.CELL_TYPE_FORMULA: // 公式
// // 得到对应单元格的公式
// //cellValue = cell.getCellFormula() + "#";
// // 得到对应单元格的字符串
// cell.setCellType(Cell.CELL_TYPE_STRING);
//
// System.out.println(cellValue);
// break;
default:
cell.setCellType(Cell.CELL_TYPE_STRING);
cellValue=cell.getStringCellValue();
}
return cellValue;
}
这里用了Excel的格式转换,因为Excel每个单元格都是有自己的单元格格式的,所以取出来的值的类型各种各样,我这里是都按字符串来处理的,通过switch的处理,如果是字符串格式的,那么直接取出里边的值,如果不是,那么将它的单元格格式设置成字符串类型,在取出来。
5)
public static String getResult(String Result,String assertion){
String result="";
int a = Result.indexOf(assertion);
if(a!=(-1)){
result="Success!";
}else{
result="Failed!";
}
return result;
}
这段代码就是一个断言处理,我们通过设置报文成功返回结果的断言,然后看他是否在这次结果的字符串中来判断这次请求成功了还是失败了。
6)
import java.util.Map;
public class ExcelBean {
private String *;
private String **
private String *;
private String *;
private Map
private String *;
private String *;
public String getURL() {
return URL;
}
public void setURL(String uRL) {
URL = uRL;
}
public String get*() {
return *;
}
public void set*(String *) {
*= *;
}
public String get*() {
return *;
}
public void set*(String *) {
*= *;
}
public String get*() {
return *;
}
public void set*(String *) {
*= *;
}
public Map
return PARA;
}
public void setPARA(Map
PARA = pARA;
}
public String getMSG() {
return MSG;
}
public void setMSG(String mSG) {
MSG = mSG;
}
public String getASSERTION() {
return ASSERTION;
}
public void setASSERTION(String aSSERTION) {
ASSERTION = aSSERTION;
}
}
这个就是我的bean,为了大家理解,我还是留下了一些不涉及业务的信息。
这就是一个轻量级的自动化测试工具雏形了,这里我再说说我主要遇到的麻烦,第一个就是处理单元格格式,因为如果你不设置他会将读出来的当成浮点数或其他类型的数,这样不方便我们进行字符串转换,后来通过设置格式解决,还有一个就是我们每次判断断言后都有一个结果,这个结果反写的时候需要打开工作簿,然后关闭,但是我怎么都找不到close()方法,如果你很细心就可以看出我反写的时候打开工作簿用的是XSSFWorkbook,这里是同事给的包,找到了关闭的方法,如果你写一次不关闭工作簿,那么第二次写的时候就会报错。
当我们能做成接口自动化以后,就可以将这些与jenkins结合,然后每天都会收到邮件,这里我还在研究,后续会给大家分享。