java脚本接口自动化测试_接口自动化测试实践的记录
接口測試實踐的記錄
在敏捷開發交付的流程中,自動化測試實際上被放在一個看起來挺重要的位置,而自動化測試中,接口測試是一個投入產出比比較高的
一種自動化測試的形式,而我自己也做了一個這樣的腳手架一樣的東西可以方便進行自動化測試,關鍵是在一些現有第三包的基礎上做實現,其實一個腳手架不需要幾個 JAVA 類就可以完成了,至少我自己的這個在 10 個文件以內.要論行數估計也沒有多少代碼量,主要時間其實都是在想怎么更方便的寫自動化測試,怎么使用以后的開源代碼了。
下面介紹一下我自己如何完成這個自動化接口測試
腳手架設計和實現的,以及我自己實現過程中的種種發現。主要從以下幾個方面來講:
如何構建接口自動化測試的腳手架
關于接口測試參考的一些資源
關于接口測試的后續的一些想法
如何構建接口自動化測試的腳手架
接口測試本文中主要是指 HTTP 的請求,構建接口自動化測試腳手架的時候,首先先看看平常接口測試,測試人員時如何做的,我了解主要是以下幾種方式:
通過操作頁面/APP 來觸發接口調用
使用諸如 SOAPYUI/JMETER/POSTMAN 或者其他的客戶端工具來進行接口測試
我自己都使用過 SOAPUI/JMETER/POSTMAN,不能說使用的多么深入,但是常用的功能也都有用過,比如 SOAPUI 構建一個項目完整的接口自動化測試用例,大概有 200+ 以上的用例,可以支持不同的測試環境,檢查點中可以檢查數據庫,使用 XPATH/XQUERY 來檢查/獲取指定的值,進行不同 API 的數據傳遞等等,這些工具 (指功能測試方面) 大體的邏輯我覺得是類似的,基本上都有:
發起請求的客戶端,需要測試人員構建,也有通過 WSDL/WADL 自己生成的,不過數據都是需要測試人員輸入的
根據表達式進行取值的 Resolver,就是可以根據 XPATH/XQUERY 語法,或者其他的語法來獲取指定的值,
就是用來傳遞上下文數據的一種方式
外部可以參數話數據,比如環境配置
可以查看測試結果,這個其實可以理解為某種測試框架的一個功能,比如 JUNIT,TESTNG
接口自動化測試腳手架的構建
根據以上的分析如果自己需要實現的話,最主要需要實現一下其實就是請求的構建,請求構建包括了:
發起請求的客戶端
請求數據的構建
對于發起請求的客戶端就直接使用了 Spring RestTemplate,考慮的主要原因如下:
使用相對比較方便,模塊化比較清晰
可以使用 HTTPClient 的實現
Spring RestTemplate 所在的包還有其他一些接口的支持,以后如果使用其他接口可以不需要換包也可以做
在實際的使用過程中,其實也遇到了一些問題,比如如下的內容:
HTTPS 的訪問
開發接口定義不夠準確的問題,造成使用 RestTemplate 時候出現了一些不在開始預期范中的問題
如何解決這些問題,在后面再詳細介紹,這里說明一下使用 RestTemplate 的一個主要流程:
1. 構建請求,設置請求的 Header,URL,Accept,ContextType,Token 等等
2. 調用請求獲取返回的 Response,
這個 ResponseRestTemplate 中實際上封裝了一個 ResponseEntity 的類,里面包括了請求狀態,Body 之類
RestTemplate 有個好處就是如果給 RestTemplate 設定了 MessageConverter 的話,他可以自動把請求的返回類型直接轉換,比如你發起請求的時候設置了 JOSN 的 Message Converter,他可以幫你把類,或者字符串自己轉化為 JSON 來發送,同樣如果是返回值是 JSON 的話,也可以幫你自己將 JSON 轉換成你指定類型的 JAVA BEAN
說完這個流程,我們就說說如何通過 RestTemplate 構建一個簡單的 HTTP 請求:
Map urlVariable = new Map ();
urlVariable.put("q","test");
JavaBean javaBean = restTemplate.getForObject("http://www.baidu.com",JavaBean.class,urlVariable);
JavaBean javaBean1 = restTemplate.postForObject("http://www.baidu.com",JavaBean.class,urlVariable);
ResponseEntity e = restTemplate.getForEntity("http://www.baidu.com",JavaBean.class,urlVariable);
實際上使用 RestTemplate 還是挺簡單的,不過為了讓使測試更為方便一點,然后每個人的代碼更統一點,自己重新封裝了一下 RestTemplate 的使用,主要分為三個概念:
Service 的描述
測試數據
客戶端調用
接口服務描述
Service 的描述實際上就是一個 JSON 文件,只不過自己規定了一下,格式類似于,這個文件描述了 API 的定義,當然 API 的 body 沒有在這個里面,不過為了不把事情搞復雜,就暫時不放在這個里面.
{
"apiDomainName": "applicationName",
"contentType": "application/x-www-form-urlencoded",
"headers": {
"Accept": "application/json, text/javascript, */*"
},
"method": "POST",
"pathParameters": [],
"queryParameters": [
"username",
],
"resourceURL": "/application/subdomain"
}
測試數據類:
private Map queryParameters = Maps.newHashMap();
private Map pathParameters = Maps.newHashMap();
private Map headers = Maps.newHashMap();
private T body;
而如何調用客戶端就變成,而且其實每一個 API 的訪問其實都可以這樣子來做,
ResponseEntity response = RestTemplateHelper.build(serviceDescriptionPath,requestData).call();
說明一下的是:
serviceDescriptionPath 就是接口的描述
requestData 就是需要進行測試的數據
然后實際上接口的描述是開發還沒有開發好的時候就已經定了的,所以這里的變量就變成如何構建 requestData 了
構建 RequestData
構建 requestData 實際上就是設計測試用例,那么這里也是使用 Excel 的方式,將不同的值填寫到 excel 里面,不過為了減少 set 值這樣的操作,這個腳手架就提供了一些工具,可以直接將數據設置到 RequestData 實例,具體的操作如下:
Excel 是如下格式的:
變量名
測試用例 1
測試用例 2
data.queryParameters(username)
1
1
data.queryParameters(year)
2015
2014
data.queryParameters(month)
10
11
說明一下,通過反射的方式,可以直接生成一個 requestData 的實例,同時 queryParameters 中值已經設置好了,這樣調用代碼中就不需要寫類似于:
RequestData data = new RequestData();
data.queryParameters.put("username","1");
data.queryParameters.put("year","2015");
這里有興趣的同學可以參考這個包:里面其實已經有很方便的通過反射去賦值了,
org.jodd
jodd-bean
3.6.6
使用 TestNG 的 DataProvider
剛才講述了如何發生生成數據,那么通過 Excel 的方式提供不同的數據,就可以通過 TestNG 的 DataProvider 了
所以測試數據通過,TestNG data provider 的實現在這里就不多少了,網上其實有很多內容了.
接口測試的代碼看起來就是這個樣子了 @DataProvider(name = "data")
public Iterator getAPITestData(Method m) throws Exception {
Map clazz = new HashMap();
clazz.put("RequestData", RequestData.class);
Iterator y = TestData.provider("testcase/api1.xls", m, clazzMap);
return y;
}
@Test(dataProvider = "data")
public void testAPITest(RequestData data) {
ResponseEntity response = RestTemplateHelper.build(serviceDescriptionPath,requestData).call();
Assert.assertEqual(response.getStatus,200); // response 的期望值實際可以通過dataprovider傳入
}
而且幾乎所有的代碼都差不多成這個樣子了,那么獲取可以寫個代碼生成的東西,當然最后通過了 JsonPath 寫了一些獲取 JSON 值的工具,這個暫時也就不說了.
那么代碼生成吧
當封裝好這些東西之后,發現所有的接口都類似了,然后就做了代碼生成的工具了,代碼生成器的入口實際上個就是那個服務描述文件開始的,
所以代碼生成器的參數就是服務描述文件,在實際的使用的過程中,接口描述這個文件也可以自動生成,目前總共支持以下幾種:
手動編寫描述文件
抓取開發 API 規格網站接口的描述,自動生成描述文件
解析 HAR 文件自動生成描述文件,解析 HAR 其實不難,就是繁瑣一點字段有點多
后續想打通和 POSTMAN 的連接,可以接收 POSTMAN 的導出文件,然后也可以導出 POSTMANT 的,以后開 BUG 就什么也不說,直接放一個 POSTMAN 文件其實也挺帥的
至此一個接口測試的腳手架就大致完成了.總結起來就是:
封裝了 RestTemplate,讓他接受一個接口的描述文件,一個請求的數據
通過 Excel 傳數據給請求的數據進行數據驅動
相同類似的代碼進行代碼生成
最后其實這樣子使用下來,接口構建幾個簡單一點的自動化測試用例,其實也就是幾分鐘的事情.
一些細節
在實現過程中,實際上還有一些特殊情況,比如說需要 token,認證信息,這些通過一個公用函數的方式就可以解決,然后在代碼生成的時候
直接講這個放在實際測試的接口前面調用. 后有就是上面說到的的:
HTTPS 的訪問
開發接口定義不夠準確的問題,造成使用 RestTemplate 時候出現了一些不在開始預期范中的問題
HTTPS 的訪問是通過如下代碼解決的,創建一個略 SSL 的 httpclient 就可以了
public static RestTemplateClientHelper getHttpClientImplInstance(){
RestTemplateClientHelper client = new RestTemplateClientHelper();
HttpClient httpClient = getIgnoreSSLHttpClient();
client.setTemplate(new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient)));
return client;
}
/**
* 獲取忽略SSL的httpclient,支持https的請求
* @return
*/
private static HttpClient getIgnoreSSLHttpClient() {
CloseableHttpClient httpClient = null;
try {
httpClient = HttpClients.custom().
setHostnameVerifier(new AllowAllHostnameVerifier()).
setSslcontext(new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
return true;
}
}).build()).build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
logger.error(e);
}
return httpClient;
}
還有一個就是有時開發的接口返回類型 (accept type) 不能讓 RestTemplate 處理,那么其實添加自己定義個 MessageConverter 就好了:
下面是一個修改阿里自己的 FastJSON 的 MessageConverter 的例子,
其實也沒改什么,就是捕捉了一個異常,主要是不知道什么原因調用時候 readInternal 就拋出和編碼格式有關系的異常,然后就捕捉了一下異常反正也就把那個問題就沒有了,不過這個改法應該也是有問題的.
public class ModifiedFastJsonHttpMessageConverter extends AbstractHttpMessageConverter {
........
public ModifiedFastJsonHttpMessageConverter() {
super(new MediaType("application", "json", UTF8), new MediaType("application", "*+json", UTF8));
this.charset = UTF8;
this.features = new SerializerFeature[0];
}
............
protected Object readInternal(Class> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream in = inputMessage.getBody();
byte[] buf = new byte[1024];
while(true) {
int bytes = in.read(buf);
if(bytes == -1) {
byte[] bytes1 = baos.toByteArray();
try {
return JSON.parseObject(bytes1, 0, bytes1.length, this.charset.newDecoder(), clazz);
}catch (Exception e){
return baos.toString("UTF-8");
}
}
if(bytes > 0) {
baos.write(buf, 0, bytes);
}
}
}
........
}
后續的一些想法
后續希望在這個基礎上再做點其他的一些事情:
增加 POSTMAN 的代碼生成的支持
探索能不能通過 API 接口描述直接生成 JMETER 的 JMX 文件,可以講基礎的 JMETER 性能測試的基礎代碼也生成好
整理一下放到 GITHUB 上面,其實整個腳手架自己也就是幾個文件而已,:)
建立一個 MOCK SERVER,方便模擬一些 API 調用的方式
做一個簡單點獲取 JSON 中指定字段,然后傳遞給下一個 API 使用的工具
一些資源
總結
以上是生活随笔為你收集整理的java脚本接口自动化测试_接口自动化测试实践的记录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue 右边跳转 实现左侧栏_Vue 后
- 下一篇: springboot中接口实例化_Ang