接口自动化实现

一.实现框架:

 java+maven+testng+reportNG+jenkins框架

二.框架原理:

使用脚本发送HTTP请求返回接口的响应结果,并将代码存放在svn,Git中,jenkins可以设置测试的时间自动获取代码,编辑和运行。

三.环境部署和安装:

1.安装JDK1.8,配置相关的环境变量;

2.安装eclipse;

3.在eclipse中安装maven,svn,testng插件;

四.详细实现:

1.详情:

2.封装http请求方法:

package com.jdapi.util;

/**
* HttpRequest.java Created on
* @author
* @version 1.0
* 封装GET,PUT,POST,Delete请求
*/

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.Objects;
import org.apache.log4j.Logger;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;


public class HttpRequest {

private Logger logger = Logger.getLogger(this.getClass());

/**
* @param path
* @param query
* @param header
* @param json
* query拼接在请求地址后面,类似url?query1=value1&query2=value2
* header为空则填null,不为空则直接调用getOfflineHeader方法
* json参数从excel表格中获取json格式的字符串
* @return
* @throws IOException
*/
public String sendPost(String path,Map<String,String> query,Map<String,String> header,String json) throws IOException{

OkHttpClient client = new OkHttpClient();
StringBuilder url = new StringBuilder(path);
Request request = null;
String result = "";
if (Objects.nonNull(query) && Objects.nonNull(json) && Objects.isNull(header)) {
url.append("?");
query.forEach((k, v)->{
url.append(k).append("=").append(v).append("&");
});
String temporaryUrl = url.substring(0,url.length()-1);
url.setLength(0);
url.append(temporaryUrl);

RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),json);
body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),json);
request = new Request.Builder()
.url(url.toString())
.post(body)
.build();
result = client.newCall(request).execute().body().string();
}

if(Objects.nonNull(query) && Objects.isNull(header) && Objects.isNull(json)){
BufferedReader in = null;
OutputStreamWriter out = null;
StringBuilder rs = new StringBuilder();
StringBuilder realUrl = new StringBuilder(path);
try {
url.append("?");
query.forEach((k, v)->{
url.append(k).append("=").append(v).append("&");
});
String temporaryUrl = url.substring(0,url.length()-1);
url.setLength(0);
url.append(temporaryUrl);
URL requestUrl = new URL(realUrl.toString());
HttpURLConnection conn = (HttpURLConnection)requestUrl.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setDoInput(true);
//设置连接超时时间和读取超时时间
conn.setConnectTimeout(10000);
conn.setReadTimeout(10000);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
out = new OutputStreamWriter(conn.getOutputStream());
out.flush();
out.close();
// 取得输入流,并使用Reader读取
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
rs.append(line);
}

} catch (Exception e) {
e.printStackTrace();
}
//关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
result = rs.toString();


}

if(Objects.nonNull(query) && Objects.nonNull(json) && Objects.nonNull(header)){
url.append("?");
query.forEach((k, v)->{
url.append(k).append("=").append(v).append("&");
});
String temporaryUrl = url.substring(0,url.length()-1);
url.setLength(0);
url.append(temporaryUrl);
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),json);
body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),json);
request = new Request.Builder()
.url(url.toString())
.headers(Headers.of(header))
.post(body)
.build();
result = client.newCall(request).execute().body().string();
}
if(Objects.isNull(query) && Objects.nonNull(json) && Objects.nonNull(header)){
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),json);
body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),json);
request = new Request.Builder()
.url(url.toString())
.headers(Headers.of(header))
.post(body)
.build();
return client.newCall(request).execute().body().string();
}

if(Objects.isNull(query) && Objects.nonNull(json) && Objects.isNull(header)){
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),json);
body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),json);
request = new Request.Builder()
.url(url.toString())
.post(body)
.build();
result = client.newCall(request).execute().body().string();
}

return result;
}

/**
*
* @param path
* @param query
* @param header
* @param json
* query拼接在请求地址后面,类似url?query1=value1&query2=value2
* header为空则填null,不为空则直接调用getOfflineHeader方法
* @return result 请求结果
* @throws IOException
*/
public String sendGet(String path,Map<String,String> query,Map<String,String> header,String json) throws IOException{

OkHttpClient client = new OkHttpClient();
StringBuilder url = new StringBuilder(path);
String requestUrl = null;
Request request = null;
String result = null;
if(Objects.nonNull(query) && Objects.isNull(header) && Objects.isNull(json)){
url.append("?");
query.forEach((k, v)->{
url.append(k).append("=").append(v).append("&");
});
String temporaryUrl = url.substring(0,url.length()-1);
url.setLength(0);
url.append(temporaryUrl);

if(url.toString().contains("\"\"")){
requestUrl = url.toString().replace("\"\"", "");
}else{
requestUrl = url.toString();
}

request = new Request.Builder()
.url(requestUrl)
.build();
result = client.newCall(request).execute().body().string();

}
if(Objects.nonNull(query) && Objects.nonNull(header) && Objects.nonNull(json)){
url.append("?");
query.forEach((k, v)->{
url.append(k).append("=").append(v).append("&");
});
String temporaryUrl = url.substring(0,url.length()-1);
url.setLength(0);
url.append(temporaryUrl);

if(url.toString().contains("\"\"")){
requestUrl = url.toString().replace("\"\"", "");
}else{
requestUrl = url.toString();
}
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),json);
request = new Request.Builder()
.url(requestUrl)
.headers(Headers.of(header))
.post(body)
.build();
result = client.newCall(request).execute().body().string();
}
return result;

}

/**
* @param url
* @param path
* @param json
* 请求地址:url/path1/path2,请求json字符串放在body中
* @return result
* @throws IOException
*/

public String sendPut(String url,String[] path,String json) throws IOException{

OkHttpClient client = new OkHttpClient();
StringBuilder realUrl = new StringBuilder(url);
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),"");

//如果请求中带有query参数,则拼接在path后面
if(Objects.nonNull(path)){
for(int i=0;i<path.length;i++){
realUrl.append("/").append(path[i]);
}
}
logger.debug("实际请求地址是:"+realUrl.toString());
Request request = new Request.Builder()
.url(realUrl.toString())
.put(body)
.build();
return client.newCall(request).execute().body().string();
}


/**
* @param url
* @param path
* 请求地址:url/path1/path2
* @return result
* @throws IOException
*/
public String sendDelete(String url,String[]path) throws IOException{
OkHttpClient client = new OkHttpClient();
StringBuilder realUrl = new StringBuilder(url);
if(Objects.nonNull(path)){
for(int i=0;i<path.length;i++){
realUrl.append("/").append(path[i]);
}
}

Request request = new Request.Builder()
.url(realUrl.toString())
.build();
return client.newCall(request).execute().body().string();
}

public interface OnResponseCallback {
void onResponse(String str);
}


public String sendPostWithUrlAndQuery(String path,Map<String,String> query){
BufferedReader in = null;
OutputStreamWriter out = null;
StringBuilder result = new StringBuilder();
StringBuilder url = new StringBuilder(path);
try {
url.append("?");
query.forEach((k, v)->{
url.append(k).append("=").append(v).append("&");
});
String temporaryUrl = url.substring(0,url.length()-1);
url.setLength(0);
url.append(temporaryUrl);
URL realUrl = new URL(url.toString());
HttpURLConnection conn = (HttpURLConnection)realUrl.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setDoInput(true);
//设置连接超时时间和读取超时时间
conn.setConnectTimeout(10000);
conn.setReadTimeout(10000);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
out = new OutputStreamWriter(conn.getOutputStream());
out.flush();
out.close();
// 取得输入流,并使用Reader读取
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
result.append(line);
}

} catch (Exception e) {
e.printStackTrace();
}
//关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result.toString();
}
}

 3.json解析:

package com.jdapi.util;

import java.util.Map;
import org.apache.log4j.Logger;
import com.google.gson.GsonBuilder;


public class AnalyzeJson {


private static Logger logger = Logger.getLogger(AnalyzeJson.class);

/**
* 封装了响应结果中带有list数组和data不同情况下
* 取出return_msg字段值的方法
* responseResult 是请求响应结果
* dataType 表示return_data返回字段中是否包括数组,如果有数组则此参数传list,不包括数组则此参数传data,缺失data字段则传emptyData
*/

public static String getresultmsg(String responseResult,String responseType){
try{
if(responseType.equals("list")){
ListResponseResult resultObj = new GsonBuilder().create().fromJson(responseResult,ListResponseResult.class);
return resultObj.resultmsg();
}else if(responseType.equals("data")){
ResponseResult resultObj = new GsonBuilder().create().fromJson(responseResult,ResponseResult.class);
return resultObj.resultmsg();
}
}catch(Exception e){
e.printStackTrace();
logger.debug("响应结果类型传参有误,请输入list,data,emptyData中的一种类型");
}
return null;
}


/**
* 根据接口请求返回数组分类,解析返回字段
* @param responseResult
* @param dataType
* @param field
* @return
* @throws Exception
*/
public static String getValue(String responseResult,String dataType,String field) throws Exception{

try{
if(responseResult.length() != 0){
if(dataType.equals("list")){
ListResponseResult resultObj = new GsonBuilder().create().fromJson(responseResult,ListResponseResult.class);
for(Map<String, Object> o : resultObj.getData()){
return (String)o.get(field);
}
}else if(dataType.equals("data")){
ResponseResult resultObj = new GsonBuilder().create().fromJson(responseResult,ResponseResult.class);
return resultObj.getData().get(field).toString();
}
}
}catch(Exception e){
e.printStackTrace();
logger.debug("json字段类型传参有误,请输入list,data,或者null!");
}
return null;
}

/**
* 判断return_data是否返回空数组,如果为空数组则返回true,不为空数组则返回false
* @param responseResult
* @param dataType
* @return
*/
public static boolean isReturnDataEmpty(String responseResult,String dataType){
if(responseResult.length() != 0){
if(dataType.equals("list")){
ListResponseResult resultObj = new GsonBuilder().create().fromJson(responseResult, ListResponseResult.class);
if(resultObj.getData().toString().equals("[]")){
return true;
}
return false;
}else if(dataType.equals("data")){
ResponseResult resultObj = new GsonBuilder().create().fromJson(responseResult, ResponseResult.class);
if(resultObj.getData().toString().equals("[]")){
return true;
}
return false;
}
}
return true;
}

}

4.excel数据读取:

package com.jdapi.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

public class ExcelReader {
private String filePath;
private String sheetName;
private Workbook workBook;
private Sheet sheet;
private List<String> columnHeaderList;
private List<List<String>> listData;
private List<Map<String,String>> mapData;
private boolean flag;

public ExcelReader(String filePath, String sheetName) {
this.filePath = filePath;
this.sheetName = sheetName;
this.flag = false;
this.load();
}

private void load() {
FileInputStream inStream = null;
try {
inStream = new FileInputStream(new File(filePath));
workBook = WorkbookFactory.create(inStream);
sheet = workBook.getSheet(sheetName);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(inStream!=null){
inStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}


private String getCellValue(Cell cell) {
String cellValue = "";
DataFormatter formatter = new DataFormatter();
if (cell != null) {
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
cellValue = formatter.formatCellValue(cell);
} else {
double value = cell.getNumericCellValue();
int intValue = (int) value;
cellValue = value - intValue == 0 ? String.valueOf(intValue) : String.valueOf(value);
}
break;
case Cell.CELL_TYPE_STRING:
cellValue = cell.getStringCellValue();
break;
case Cell.CELL_TYPE_BOOLEAN:
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
cellValue = String.valueOf(cell.getCellFormula());
break;
case Cell.CELL_TYPE_BLANK:
cellValue = "";
break;
case Cell.CELL_TYPE_ERROR:
cellValue = "";
break;
default:
cellValue = cell.toString().trim();
break;
}
}
return cellValue.trim();
}

private void getSheetData() {
listData = new ArrayList<List<String>>();
mapData = new ArrayList<Map<String, String>>();
columnHeaderList = new ArrayList<String>();
int numOfRows = sheet.getLastRowNum() + 1;
for (int i = 0; i < numOfRows; i++) {
Row row = sheet.getRow(i);
Map<String, String> map = new HashMap<String, String>();
List<String> list = new ArrayList<String>();
if (row != null) {
for (int j = 0; j < row.getLastCellNum(); j++) {
Cell cell = row.getCell(j);
if (i == 0){
columnHeaderList.add(getCellValue(cell));
}
else{
map.put(columnHeaderList.get(j), this.getCellValue(cell));
}
list.add(this.getCellValue(cell));
}
}
if (i > 0){
mapData.add(map);
}
listData.add(list);
}
flag = true;
}

public String getCellData(int row, int col){
if(row<=0 || col<=0){
return null;
}
if(!flag){
this.getSheetData();
}
if(listData.size()>=row && listData.get(row-1).size()>=col){
return listData.get(row-1).get(col-1);
}else{
return null;
}
}

public String getCellData(int row, String headerName){
if(row<=0){
return null;
}
if(!flag){
this.getSheetData();
}
if(mapData.size()>=row && mapData.get(row-1).containsKey(headerName)){
return mapData.get(row-1).get(headerName);
}else{
return null;
}
}

public Map<String,String> getQueryToMap(int row,String headerName){
String result;
String[] sourceStrArray;
Map<String,String> mp = new HashMap<String,String>();
if(row<=0){
return null;
}
if(!flag){
this.getSheetData();
}

if(mapData.size()>=row && mapData.get(row-1).containsKey(headerName)){
result = mapData.get(row-1).get(headerName);
sourceStrArray = result.split("&");
if(sourceStrArray.length>=2){
for(int i=0;i<sourceStrArray.length;i++){
String[] ary = sourceStrArray[i].split("=");
for(int j=1;j<ary.length;j++){
mp.put(ary[j-1],ary[ary.length-1]);
}
}
}else{
String[] ary = result.split("=");
mp.put(ary[0], ary[ary.length-1]);
}
return mp;
}else{
return null;
}
}

}

 5.excel数据:

 

6.测试代码:

package com.jdapi.testcase;

import org.testng.annotations.Test;
import com.jdapi.util.ExcelReader;
import com.jdapi.util.AnalyzeJson;
import com.jdapi.util.HttpRequest;
import com.jdapi.util.Assertion;
import org.apache.log4j.Logger;

public class NewTest {

private Logger logger = Logger.getLogger(this.getClass());
private String excelPath = "D:\\testdata\\test.xlsx";
private String sheet = "京东天气预报接口";
ExcelReader excelReader = new ExcelReader(excelPath, sheet);
HttpRequest httpRequest = new HttpRequest();
AnalyzeJson analyzeJson = new AnalyzeJson();
private String result = "";

@Test
public void test_NewTest() throws Exception
{
result = httpRequest.sendGet(excelReader.getCellData(1, "url"), excelReader.getQueryToMap(1, "query"),null, null);
logger.info("接口响应结果:"+result);
Assertion.verifyEquals(AnalyzeJson.getresultmsg(result, "data"),excelReader.getCellData(1, "expectedResult"));
logger.info("实际结果是:"+AnalyzeJson.getresultmsg(result, "data"));
logger.info("预期结果是:"+excelReader.getCellData(1, "expectedResult"));

}

}

 7.运行结果:

 

 

 总结:需要学习的知识点为java相关网络编程,例如http请求不同方法的封装,json的解析以及分层解析,连接数据库操作数据库,文件读取;基本功日志相关;

其中个人认为在实现的过程中难点:

1.json的解析尤其是遇到不同返回结果,多层实现的时候就比较困难;

2.断言现在只是基本的实现和文件预期结果进行对比判断;

3.请求头的封装;

4.签名的封装;

5.接口格式一定要完全统一;

后期优化实现方向:

1.json多层解析;

2.断言数据库进行判断;

3.报告优化;

 

posted @ 2018-02-27 11:35  ReturnHome  阅读(7240)  评论(0编辑  收藏  举报