写在开头: 技术渣做接口自动化,大神们请轻喷!多提提优化方案和问题点。
以前做接口测试一直通过 postman 和 soapUI 来做,Postman 是 Chrome 的一个插件 Case 多了不好管理,同时执行起来麻烦,得一个一个去点击执行,平时做调试可以用用真正用来做接口自动化不合适。
SoapUI(改名叫 Ready! API)是个不错的工具,同时支持了 soap 类型和 rest 类型的接口,而且还支持安全,性能等测试,当然它是个商业工具,高级功能都是需要收费的,想那啥也是可以的,但是工具提供了方便同样可扩展性差了点,而且我经常遇到莫名其妙的工具问题,也许是因为我用的是那啥版本,稳定性差吧。
也是有人直接用 Jmeter 或者 loadrunner 来做接口自动化的,当然也是行的当用例管理上也是较为麻烦,有个框架 robot framework,关键字驱动来做接口也是一朋友一再推荐的做法,可惜我对 python 不熟悉,尽管上手容易我还是放弃。
现在我改用这么一套思路在做,因为目前我的接口协议都是 http 的,我就干脆直接用 java 的 HttpClient,然后接口返回是 json 格式,我就引入了 json-lib 来方便解析获取,同样因为需要跟数据库交互所以又引入了 MyBatis,同时用例还是沿用 TestNG ,为了更方便管理接口(地址,路径,参数等等)又通过 excel 来管理接口,通过 excel 来驱动测试。 这样下来整个项目就涉及了 httpclient+json+mybaits+testng+poi(excel)+log4j 等框架包。
在这过程做了一些封装一些主要代码如下:
对 httpclient 封装,只要把接口的完整请求传进来如果请求正常,就会 return 的接口返回的 json:
public static JSON getAPI(URI uri) throws URISyntaxException, IOException {
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
httpget = new HttpGet(uri);
log.info("执行API请求" + httpget.getRequestLine());
ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
public String handleResponse(
final HttpResponse response) throws ClientProtocolException, IOException {
int status = response.getStatusLine().getStatusCode();
if (status >= 200 && status < 300) {
HttpEntity entity = response.getEntity();
return entity != null ? EntityUtils.toString(entity) : null;
} else {
log.error("请求错误,状态码为:"+response.getStatusLine().getStatusCode());
throw new ClientProtocolException("意外的状态返回: " + status);
}
}
};
String responseBody = httpclient.execute(httpget, responseHandler);
JSONObject dataObject = JSONObject.fromObject(responseBody);
return dataObject;
} finally {
httpclient.close();
}
}
那请求可以发起了,接口 URL 怎么来? 刚说通过 excel 来管理接口了,例如我新建了下面这么个文件:
TID 用来标识我需要读取哪行数据,TName 仅仅做说明这个接口是什么接口,Method 来表示接口是什么类型,根据不同类型做调用不同的 httpclient 封装方法,然后后面就是去拼接接口的 URL:
拼接 URL 的关键代码如下:
/**
* 请求链接拼接
*
* @param tid 哪一行的excel数据
* @param parameters 参数
* @return uri
*/
public static URI returnURI(String tid, String... parameters) {
String path = System.getProperty("user.dir") + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator + "excel" + File.separator + "api.xls";
ExcelEngine.filepath = path;
ExcelEngine.sheetname = "api";
// 从excel 拿数据
List apiData = getApiData(tid);
String getorpost = ((String) apiData.get(2)).toLowerCase();
// System.out.println(getorpost);
String scheme = (String) apiData.get(3);
String apiHost = (String) apiData.get(4);
String apiPath = (String) apiData.get(5);
// URI 拼接
StringBuffer stringBuffer = new StringBuffer(scheme + "://" + apiHost + apiPath + "?");
HashMap<String, String> hashmap = new HashMap();
int p = 0;
while (p < parameters.length) {
hashmap.put((String) apiData.get(p + 6), parameters[p]);
p = p + 1;
}
hashmap.put("autoKey", String.valueOf(Parameters.timeStamp_Long()));
// int i = hashmap.size();
// System.out.println("map 大小" + i);
int num = 0;
// System.out.println("map 里面的值" + hashmap.entrySet());
for (HashMap.Entry<String, String> entry : hashmap.entrySet()) {
num++;
if (num == hashmap.size()) {
stringBuffer.append(entry.getKey() + "=" + entry.getValue());
} else {
stringBuffer.append(entry.getKey() + "=" + entry.getValue() + "&");
}
}
String url = stringBuffer.toString();
URI uri = URI.create(url);
return uri;
}
现在接口的 URL 拼接完成了,请求也发起了,也可以拿到返回的 json 数据了,最后就得对返回的数据做校验了,这里我是重新封装了下 TestNG 提供的 Assert 类为 TaquAssert 类,其实没做多大改变加了几个方法而已,下面是一个完整的登陆例子:
public class LoginTest {
static LoggerControler log = LoggerControler.getLogger(LoginTest.class);
// accounts 表
AccountsTest accountsTest = new AccountsTest();
String tid = "v1_Account_login";
@Test
public void loginSuccess() {
// 发起api请求
JSONObject json = ApiEngine.taquAPI(tid, "username", "password");
// 打印出json
log.info(json);
// 通过api获取该用户的account_id,然后查询Accounts表
String account_id = json.getJSONObject("info").getJSONObject("data").getString("account_id");
Accounts accounts = accountsTest.byAccount_id(Integer.valueOf(account_id));
// 校验返回的 状态是不是 success.
String response_status = json.getString("response_status");
TaquAssert.assertEquals("校验response_status", "success", response_status);
// 从数据库获取用户名和接口返回的用户名做对比检查是否一致
String account_name_sql = accounts.getAccount_name();
String account_name_api = json.getJSONObject("info").getJSONObject("data").getString("nickname");
TaquAssert.assertEquals("校验account_name", account_name_api, account_name_sql);
}
}
后期还会把这块放到 Jenkins 环境去运行,之前把 Jenkins 环境搞坏了,苦逼还得去重搭建 。
OK 以上就是目前做接口自动化的大概思路,这其中肯定还有非常多需要去做优化的, 望各大神提提优化意见和方案,小弟不胜感激。