java自动化数据处理流程控制_基于Java+HttpClient+TestNG的接口自动化测试框架(十)------ 测试步骤过程中的数据处理...

我们在做接口自动化测试的时候,首先先要想想接口的请求是怎样完成的,或者说,单个的接口请求有哪些要素。以及一些不同请求的不同应对方法。

简单来说,一个接口测试有几个要素。我们需要挨个的罗列出来。

0)是否运行该测试。(有个开关控制)

1)请求的url。(必须的)

2)请求的header。--------这个来说有点点复杂。一些常用的请求头内容还比较好说。但是,当Content-Type的值有变化的时候,参数需要进行分别的处理。另外,还有一种就是认证需要加Token的情形。

3)请求参数。--------通常来说,这部分也是有些复杂的,请求参数会多种多样。当然,目前绝大多数的情况还都是Json和文件。

4)请求结果的判定--------返回Json字符串的判定。某些请求会出现图片和文件的下载,这些也都是要注意的。

5)请求结果的转存及后续参数的提供--------具体的处理在前面已经讲过。

对于以上的要素,我们可以设计一个Excel表格来进行管理,罗列出我们需要的要素。然后通过读取该Excel,来自动的进行接口的请求,以及返回内容的判定,从而达到自动化测试的目的。

71820d437496b8877b85649cf72a7b4e.png

对于上面的形式,童鞋们可能有很多疑问。这里不展开说,只是提供一种参考。这种表格,我姑且称之为case表格。这里,我简单描述一下这个表格。首先,我们把Excel的内容进行读入,

run这一列代表是否运行这条测试(可以用Y/N来控制)。

desc这一列代表本条接口测试的说明,即输入哪个部分,干什么的。

method这个是请求方法,就是我们通常说的get/post什么的。

url这个是具体请求的链接,前面不加主机名。因为这个主机名我们可以在xml文件中进行配置。

header这个就是请求头的信息,在xml中我还会写一个public Headers的公用请求头信息。这里其实是为了碰到不同的情况。比如:我们N个请求中如果都是用到Content-Type:application/json,那么我们可以写在公用的请求头中。但是,如果某个请求需要单独加token来访问,这个时候请求头上可能要带上token的信息。这样的话,就可以在Excel文件中,这一条请求的header中指定这个token。例如:{"Authorization":"Bearer ${sys_token}"}。

param这个是参数,即访问时需要增加的参数。当然,这里也可以指定上传的文件。----关于上传文件,我们之后再详细讨论。

contains这个是我自己自定义的,因为有的时候只需要直接判定返回的内容中是否包含某段内容。如果是这样的判定(即不考虑jsonpath),就设定为Y,反之为N。

verify为判定内容。如果前面是Y,则输入具体需要判定的内容。如果是N,则需要按照JSONPath的路径来指定判定的值。

save这个为存储变量来用的。假如该条请求的某个返回信息,是下面某个请求需要的,就可以按照这个方式来处理。

依照上面的描述,在进行Excel读取的时候,我们需要将各个部分的信息先读取出来,并最终按照一定的形式,提供一个List,这个List可以看作是对每行Excel需要进行的接口请求,读取并处理了数据。(这里说的有点抽象,请参考以下的代码)

packageutils;importjava.io.File;importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.InputStream;importjava.io.OutputStream;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;importjava.math.BigDecimal;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importorg.apache.poi.hssf.usermodel.HSSFWorkbook;importorg.apache.poi.ss.usermodel.Cell;importorg.apache.poi.ss.usermodel.CellType;importorg.apache.poi.ss.usermodel.Row;importorg.apache.poi.ss.usermodel.Sheet;importorg.apache.poi.ss.usermodel.Workbook;importorg.apache.poi.xssf.usermodel.XSSFWorkbook;importcom.alibaba.fastjson.JSONObject;public classexcelUtil {/*** 获取excel表所有sheet数据

*@paramclz

*@parampath

*@return

*/

public static List readExcel(Classclz, String path) {

System.out.println(path);if (null == path || "".equals(path)) {return null;

}

InputStream is;

Workbook xssfWorkbook;try{

is= newFileInputStream(path);if (path.endsWith(".xls")) {

xssfWorkbook= newHSSFWorkbook(is);

}else{

xssfWorkbook= newXSSFWorkbook(is);

}

is.close();int sheetNumber =xssfWorkbook.getNumberOfSheets();

List allData = new ArrayList();for (int i = 0; i < sheetNumber; i++) {

allData.addAll(transToObject(clz, xssfWorkbook,

xssfWorkbook.getSheetName(i)));

}returnallData;

}catch(Exception e) {

e.printStackTrace();throw new RuntimeException("转换excel文件失败:" +e.getMessage());

}

}/*** 获取excel表指定sheet表数据

*@paramclz

*@parampath

*@paramsheetName

*@return

*/

public static List readExcel(Classclz, String path,

String sheetName) {if (null == path || "".equals(path)) {return null;

}

InputStream is;

Workbook xssfWorkbook;try{

is= newFileInputStream(path);if (path.endsWith(".xls")) {

xssfWorkbook= newHSSFWorkbook(is);

}else{

xssfWorkbook= newXSSFWorkbook(is);

}

is.close();returntransToObject(clz, xssfWorkbook, sheetName);

}catch(Exception e) {

e.printStackTrace();throw new RuntimeException("转换excel文件失败:" +e.getMessage());

}

}private static List transToObject(Classclz,

Workbook xssfWorkbook, String sheetName)throwsInstantiationException, IllegalAccessException,

InvocationTargetException {

List list = new ArrayList();

Sheet xssfSheet=xssfWorkbook.getSheet(sheetName);

Row firstRow= xssfSheet.getRow(0);if(null ==firstRow){returnlist;

}

List heads =getRow(firstRow);//添加sheetName字段,用于封装至apiDataBean中,与bean中的字段相匹配。

heads.add("sheetName");

Map headMethod =getSetMethod(clz, heads);for (int rowNum = 1; rowNum <= xssfSheet.getLastRowNum(); rowNum++) {try{

Row xssfRow=xssfSheet.getRow(rowNum);if (xssfRow == null) {continue;

}

T t=clz.newInstance();

List data =getRow(xssfRow);//如果发现表数据的列数小于表头的列数,则自动填充为null,最后一位不动,用于添加sheetName数据

while(data.size()+1

data.add("");

}

data.add(sheetName);

setValue(t, data, heads, headMethod);

list.add(t);

}catch(IllegalArgumentException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}returnlist;

}private static Map getSetMethod(Class>clz,

Listheads) {

Map map = new HashMap();

Method[] methods=clz.getMethods();for(Object head : heads) {//boolean find = false;

for(Method method : methods) {if(method.getName().toLowerCase()

.equals("set" +head.toString().toLowerCase())&& method.getParameterTypes().length == 1) {

map.put(head.toString(), method);//find = true;

break;

}

}//if (!find) {//map.put(head, null);//}

}returnmap;

}/** 将具体的值确定。*/

private static void setValue(Object obj, Listdata,

List heads, Mapmethods)throwsIllegalArgumentException, IllegalAccessException,

InvocationTargetException {for (Map.Entryentry : methods.entrySet()) {

Object value= "";int dataIndex =heads.indexOf(entry.getKey());if (dataIndex

value=data.get(heads.indexOf(entry.getKey()));

}

Method method=entry.getValue();

Class> param = method.getParameterTypes()[0];if (String.class.equals(param)) {

method.invoke(obj, value);

}else if (Integer.class.equals(param) || int.class.equals(param)) {if(value.toString()==""){

value=0;

}

method.invoke(obj,newBigDecimal(value.toString()).intValue());

}else if (Long.class.equals(param) || long.class.equals(param)) {if(value.toString()==""){

value=0;

}

method.invoke(obj,newBigDecimal(value.toString()).longValue());

}else if (Short.class.equals(param) || short.class.equals(param)) {if(value.toString()==""){

value=0;

}

method.invoke(obj,newBigDecimal(value.toString()).shortValue());

}else if (Boolean.class.equals(param)|| boolean.class.equals(param)) {

method.invoke(obj, Boolean.valueOf(value.toString())|| value.toString().toLowerCase().equals("y"));

}else if (JSONObject.class.equals(param)|| JSONObject.class.equals(param)) {

method.invoke(obj, JSONObject.parseObject(value.toString()));

}else{//Date

method.invoke(obj, value);

}

}

}private static ListgetRow(Row xssfRow) {

List cells = new ArrayList();if (xssfRow != null) {for (short cellNum = 0; cellNum < xssfRow.getLastCellNum(); cellNum++) {

Cell xssfCell=xssfRow.getCell(cellNum);

cells.add(getValue(xssfCell));

}

}returncells;

}private staticString getValue(Cell cell) {if (null ==cell) {return "";

}else if (cell.getCellType() ==CellType.BOOLEAN) {//返回布尔类型的值

returnString.valueOf(cell.getBooleanCellValue());

}else if (cell.getCellType() ==CellType.NUMERIC) {//返回数值类型的值

returnString.valueOf(cell.getNumericCellValue());

}else{//返回字符串类型的值

returnString.valueOf(cell.getStringCellValue());

}

}}

基于上面的Excel读取,这里我们做成一个TestBase的类,这个类确定了各个参数的数据应该如何处理,并在最终的接口请求中,以何种形式来工作。部分代码在之前的篇章中已经进行过较为详细的说明,这里不再赘述,只为参考。请参见:基于Java+HttpClient+TestNG的接口自动化测试框架(四)-------参数存取处理

import java.nio.file.Paths;

importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importjava.util.regex.Matcher;importjava.util.regex.Pattern;importorg.dom4j.DocumentException;importorg.testng.Assert;importcom.alibaba.fastjson.JSONPath;importbean.ApiDataBean;importbean.baseBean;importutils.assertUtil;importutils.excelUtil;importutils.functionUtil;importutils.reportUtil;importutils.stringUtil;public classTestBase {/*** 公共参数数据池(全局可用)*/

private static Map saveDatas = new HashMap();/*** 替换符,如果数据中包含“${}”则会被替换成公共参数中存储的数据*/

protected Pattern replaceParamPattern = Pattern.compile("\\$\\{(.*?)\\}");/*** 截取自定义方法正则表达式:__xxx(ooo)*/

protected Pattern funPattern =Pattern

.compile("__(\\w*?)\\((([\\w\\\\\\/:\\.\\$]*,?)*)\\)");

private staticConnection myCon;

protected void setSaveDatas(Mapmap) {

saveDatas.putAll(map);

}/*** 组件预参数(处理__fucn()以及${xxxx})

*

*@paramapiDataBean

*@return

*/

protectedString buildParam(String param) {

param=getCommonParam(param);

Matcher m =funPattern.matcher(param);while(m.find()) {

String funcName= m.group(1);

String args= m.group(2);

String value;//bodyfile属于特殊情况,不进行匹配,在post请求的时候进行处理

if(functionUtil.isFunction(funcName)&& !funcName.equals("bodyfile")) {//属于函数助手,调用那个函数助手获取。

value = functionUtil.getValue(funcName, args.split(","));//解析对应的函数失败

Assert.assertNotNull(value,

String.format("解析函数失败:%s。", funcName));

param=stringUtil.replaceFirst(param, m.group(), value);

}

}returnparam;

}protected voidsavePreParam(String preParam) {//通过';'分隔,将参数加入公共参数map中

if(stringUtil.isEmpty(preParam)) {return;

}

String[] preParamArr= preParam.split(";");

String key, value;for(String prepar : preParamArr) {if(stringUtil.isEmpty(prepar)) {continue;

}

key= prepar.split("=")[0];

value= prepar.split("=")[1];

reportUtil.log(String.format("存储%s参数,值为:%s。", key, value));

saveDatas.put(key, value);

}

}/*** 取公共参数 并替换参数,处理${}

*@paramparam

*@return

*/

protectedString getCommonParam(String param) {if(stringUtil.isEmpty(param)) {return "";

}

Matcher m= replaceParamPattern.matcher(param);//取公共参数正则

while(m.find()) {

String replaceKey= m.group(1);//如果公共参数池中未能找到对应的值,该用例失败。

Assert.assertNotNull(replaceKey,

String.format("格式化参数失败,公共参数中找不到%s。", replaceKey));

String value;//从公共参数池中获取值

value =getSaveData(replaceKey);//如果值不为空,则将参数替换为公共参数池里读取到的value的值。

if(null !=value) {

param=param.replace(m.group(), value);//如果值为空,则将参数替换为字符串“null”

}else{

param= param.replace(m.group(), "null");

}

}returnparam;

}/*** 获取公共数据池中的数据

*

*@paramkey

* 公共数据的key

*@return对应的value*/

protectedString getSaveData(String key) {if ("".equals(key) || !saveDatas.containsKey(key)) {return null;

}else{returnsaveDatas.get(key);

}

}/** 判定在verfiy里面的结果。*/

protected voidverifyResult(String sourceData, String verifyStr,booleancontains) {if(stringUtil.isEmpty(verifyStr)) {return;

}//将判定字符串中的定义变量全部换成实际值。

String allVerify =getCommonParam(verifyStr);

reportUtil.log("验证数据:" +allVerify);//是否判定包含。

if(contains) {//验证结果包含

assertUtil.contains(sourceData, allVerify);

}else{//通过';'分隔,通过jsonPath进行一一校验

Pattern pattern = Pattern.compile("([^;]*)=([^;]*)");

Matcher m=pattern.matcher(allVerify.trim());while(m.find()) {

String actualValue= getBuildValue(sourceData, m.group(1));

String exceptValue= getBuildValue(sourceData, m.group(2));

reportUtil.log(String.format("验证结果,实际值为:%s,期待值为:%s", actualValue,

exceptValue));

Assert.assertEquals(actualValue, exceptValue,"验证预期结果失败。");

}

}

}/*** 获取格式化后的值

*

*@paramsourchJson

*@paramkey

*@return

*/

privateString getBuildValue(String sourchJson, String key) {

key=key.trim();

Matcher funMatch=funPattern.matcher(key);if (key.startsWith("$.")) {//jsonpath

Object x =JSONPath.read(sourchJson, key);

//为了处理x为空的情况,没有比较好的方法,只能简单处理一下if(x == null) {

key=(String)x;

}else{

key=x.toString();

}

}else if(funMatch.find()) {        //处理函数的部分

String args = funMatch.group(2);

String[] argArr= args.split(",");for (int index = 0; index < argArr.length; index++) {

String arg=argArr[index];if (arg.startsWith("$.")) {

argArr[index]=JSONPath.read(sourchJson, arg).toString();

}

}

String value= functionUtil.getValue(funMatch.group(1), argArr);

key=stringUtil.replaceFirst(key, funMatch.group(), value);

}returnkey;

}/*** 提取json串中的值保存至公共池中

*

*@paramjson

* 将被提取的json串。

*@paramallSave

* 所有将被保存的数据:aa=$.jsonpath.AA;bb=$.jsonpath.BB,将$.jsonpath.

* AA提取出来的值存放至公共池的aa中,将$.jsonpath.BB提取出来的值存放至公共池的bb中*/

protected voidsaveResult(String json, String allSave) {if (null == json || "".equals(json) || null ==allSave|| "".equals(allSave)) {return;

}

allSave=getCommonParam(allSave);

String[] saves= allSave.split(";");

String key, value;for(String save : saves) {Pattern pattern= Pattern.compile("([^;=]*)=([^;]*)");

Matcher m=pattern.matcher(save.trim());while(m.find()) {

key= getBuildValue(json, m.group(1));

value= getBuildValue(json, m.group(2));

reportUtil.log(String.format("存储公共参数 %s值为:%s.", key, value));

saveDatas.put(key, value);

}

}

}/*** 根据配置读取测试用例,可读取多个Excel的多个Sheet

*

*@paramclz

* 需要转换的类

*@paramexcelPaths

* 所有excel的路径配置

*@paramexcelName

* 本次需要过滤的excel文件名

*@paramsheetName

* 本次需要过滤的sheet名

*@return返回数据

*@throwsDocumentException*/

protected List readExcelData(Classclz,

String[] excelPathArr, String[] sheetNameArr)throwsDocumentException {

List allExcelData = new ArrayList();//excel文件數組

List temArrayList = new ArrayList();for(String excelPath : excelPathArr) {

File file= Paths.get(System.getProperty("user.dir"),

excelPath).toFile();

temArrayList.clear();if (sheetNameArr.length == 0 || sheetNameArr[0] == "") {

temArrayList=excelUtil.readExcel(clz, file.getAbsolutePath());

}else{for(String sheetName : sheetNameArr) {

temArrayList.addAll(excelUtil.readExcel(clz,

file.getAbsolutePath(), sheetName));

}

}

temArrayList.forEach((bean)->{

bean.setExcelName(file.getName());

});

allExcelData.addAll(temArrayList);//将excel数据添加至list

}returnallExcelData;

}/*** 从MySql数据库中读取测试用例

*

*@paramclz

* 需要转换的类

*@parammysqlStr

* 所需要执行的sql语句

*@return返回数据

*@throwsException*/@SuppressWarnings("unchecked")protected static List readMySql (Class clz,String mysqlStr) throwsException{

List dataList = new ArrayList();

String mydriver= "com.mysql.jdbc.Driver";//防止SSL报错信息,在连接之后加上?autoReconnect=true&useSSL=false

String myUrl = "jdbc:mysql://localhost:3306/apidata?autoReconnect=true&useSSL=false";

String user= "root"; String password = "123456";try{

Class.forName(mydriver);

}catch(Exception e) {

e.printStackTrace();

}try{

myCon=DriverManager.getConnection(myUrl, user, password);

}catch(Exception e){

e.printStackTrace();

}if(myCon == null) {

reportUtil.log(myUrl+"----------数据库连接失败");

}try{

Statement st1=myCon.createStatement();

ResultSet rs=st1.executeQuery(mysqlStr);while(rs.next()) {

ApiDataBean adb= newApiDataBean();

adb.setRun(rs.getBoolean("run"));

adb.setDesc(rs.getString("desc"));

adb.setMethod(rs.getString("method"));

adb.setUrl(rs.getString("url"));adb.setHeader(rs.getString("header"));

adb.setParam(rs.getString("param"));

adb.setContains(rs.getBoolean("contains"));

adb.setVerify(rs.getString("verify"));

adb.setSave(rs.getString("save"));

dataList.add((T) adb);

}

}catch(SQLException e) {

e.printStackTrace();

}returndataList;

}}

在上面的这段代码中,我们可以看到对应每个部分的参数对应的一些处理方式。具体来说,在读取了Excel,并将其存储起来之后,对于请求参数/判定/保存变量参数方面的处理。可以根据实际的需要,在以上的代码中进行扩展。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值