jmeter中beanshell postprocessor結合fastjson庫提取不確定個數的json參數


在項目實踐中,遇到了這樣一個問題。用jmeter作http接口測試,需要的接口參數個數是不確定的。也就是說,在每次測試中,根據情況不同,可能頁面中的列表中所含的參數個數是不確定的,那么要提取的參數個數也是不確定的,可能是1個,也可能是2個或3個,甚至更多。

例如,返回的接口消息json消息可能如下

{
"data": {
"records": [{
"DEVICE_TYPE": 194,
"DEVICE_STATUS": 0,
"ORG_NAME": "**省",
"LONGITUDE": "0.000000",
"DEVICE_NAME": "測試1",
"DEVICE_ADDR": "",
"DEVICE_ID_INT": "13",
"HAVE_VIDEO": "true",
"OWNER": "-1",
"ORIGINAL_DEVICE_ID": "44000000011325******",
"PLATFORM_ID": "44000000052005******",
"ORG_CODE": "44",
"TYPE": "1",
"DEVICE_ID": "44000000011325******",
"LATITUDE": "0.000000"
}, {
"DEVICE_TYPE": 194,
"DEVICE_STATUS": 0,
"LONGITUDE": "0.000000",
"DEVICE_NAME": "測試2",
"DEVICE_ADDR": "",
"DEVICE_ID_INT": "10",
"HAVE_VIDEO": "true",
"OWNER": "1",
"ORIGINAL_DEVICE_ID": "44010000001320******",
"PLATFORM_ID": "44000000052005******",
"ORG_CODE": "4401",
"TYPE": "1",
"DEVICE_ID": "440100000013200******",
"LATITUDE": "0.000000"
}, {
"DEVICE_TYPE": 194,
"DEVICE_STATUS": 0,
"LONGITUDE": "0.000000",
"DEVICE_NAME": "測試3",
"DEVICE_ADDR": "",
"DEVICE_ID_INT": "11",
"HAVE_VIDEO": "true",
"OWNER": "1",
"ORIGINAL_DEVICE_ID": "44010000001320******",
"PLATFORM_ID": "44000000052005******",
"ORG_CODE": "4401",
"TYPE": "1",
"DEVICE_ID": "44010000001320******",
"LATITUDE": "0.000000"
}],
"count": 3,
"usetime": 0
}
}

說是可能,是因為存在多種不同的返回結果,上述json消息中返回的有3個設備信息,但也可能是1個,也可能是2個,或者是更多,具體的數值要根據頁面狀況。我們的任務是從返回的json消息中提取所有的設備ID號(DEVICE_ID)。

個人認為,這種初始環境的不確定性本來是自動化測試的大忌,會給腳本的成功運行帶來很大的風險,但在實際應用中,由於測試環境並非是個人獨占的,每次測試時,頁面配置的變化是可以理解的存在。為了提高腳本的健壯性,最好的辦法是每次根據實際頁面的返回值,提取其中的所有參數,然后拼接好,存jmeter的內部變量以供后續接口使用。要做好這一點,光用現成的jmeter工具,尤其是我們常用的json提取器(json extractor)肯定是無法做到了,至少做不到參數拼接后續處理。如果針對不同的場景,用if控制器來做區分,又會顯得太累贅。

作為一個世界級的以java為基礎的開源工具,肯定有其他的辦法,個人感覺,jmeter搭載了beanshell就好像robot framework搭載了evaluate,一下子世界寬廣了。作為一個半吊子,jmeter還沒搞透徹,java也沒用過,又要開始研究beanshell也是有點拼。只好求助萬能的度娘。網上提到了一種beanshell postprocessor結合fastjson庫的方法,可以做json的快速高效提取。

先把配置環境說一下,我用到的是jmeter5.0,fastjson用到的是1.2.47的版本,下載地址如下http://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.47/,需要把下載下來的jar包放到jmeter的安裝路徑的lib/ext庫中,並且在jmeter test plan中引用這個jar包

在需要提取的頁面添加BeanShell后置處理器

script編寫如下:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; 
import com.alibaba.fastjson.JSONObject;
// 獲取數據
//log.info("---something---");
String response = prev.getResponseDataAsString();  // 獲取Response
//log.info("Respnse is " + response);
JSONObject responseObj = JSON.parseObject(response);  // 整個Response作為JSON對象
JSONObject resObj = responseObj.getJSONObject("data");  // 獲取某一部分對象。即,json串中{}的內容
//log.info("resObj is " + resObj);
JSONArray listArray = resObj.getJSONArray("records");  // 獲取列表。即,json串中[]的內容
// 保存數據
// 1) 列表
//log.info("listArray is "+ listArray);
//log.info("array[0] is "+ listArray.getJSONObject(0).getString("DEVICE_ID"));
int len = listArray.size();
String[] temp = new String[len];
StringBuffer sBuffer = new StringBuffer("");
for(int i=0;i<len;i++){
    temp[i]= listArray.getJSONObject(i).getString("DEVICE_ID");
    sBuffer.append(temp[i]).append(",");
//    log.info("sbuffer---"+sBuffer);
    //vars.put("deviceId"+i, temp[i]);// 保存到JMeter變量中
    //log.info("deviceIdAll===",deviceIdAll);
}
String keywordStr = sBuffer.deleteCharAt(sBuffer.length() - 1).toString();
vars.put("deviceId",keywordStr);

主要用到的API釋義如下:

1. 將json字符串反序列化成JSON對象

JSONObject com.alibaba.fastjson.JSON.parseObject(String text)

2.根據key 得到json中的json數組

JSONArray com.alibaba.fastjson.JSONObject.getJSONArray(String key)

3. 根據下標拿到json數組的json對象

JSONObject com.alibaba.fastjson.JSONArray.getJSONObject(int index)

4.. 根據key拿到json的字符串值

String com.alibaba.fastjson.JSONObject.getString(String key)

更詳細的fastjson的詳細API參考了這篇文章:https://www.cnblogs.com/qiaoyeye/p/7730288.html

總結一下,此次踩過的坑主要有如下:

1.字符串是定義好之后就不能變更的,屬於常量,和之前使用python的經驗不同,在java中對於字符串,是不能使用拼接操作的,要不斷寫字符串,得用StringBuffer類。網上找到了這段話:

當對字符串進行修改的時候,需要使用 StringBuffer 和 StringBuilder 類。

和 String 類不同的是,StringBuffer 和 StringBuilder 類的對象能夠被多次的修改,並且不產生新的未使用對象。

StringBuilder 類在 Java 5 中被提出,它和 StringBuffer 之間的最大不同在於 StringBuilder 的方法不是線程安全的(不能同步訪問)。

由於 StringBuilder 相較於 StringBuffer 有速度優勢,所以多數情況下建議使用 StringBuilder 類。然而在應用程序要求線程安全的情況下,則必須使用 StringBuffer 類。

2.運行時在控制台總是提示有這樣的錯誤"Jmeter ERROR o.a.j.u.BeanShellInterpreter: Error invoking bsh method",我一直在懷疑是fastjson這個第三方庫的使用有問題,最后發現是由於腳本中存在代碼錯誤導致的,至於錯誤的原因,自己一行一行地找,所以在腳本中我加了無數的log.info,不得不說,beanshell腳本缺乏IDLE的編碼環境,確實很不友好。

總之,通過這次的實踐,進一步擴充了自己的知識面,再一次體會到,邊走邊看,堅持往前走的魅力所在。不要想着准備好所有的必要條件再出發,要用事情來推動自己去創造條件,任何經歷都是成長。工作與生活皆如此!

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM