很久沒更新博客了,荒廢了很久了,今天更新一下博客,主要記錄一下子最近遇到的問題和解決方法👱♀
這篇文章主要記錄的是jmeter批量跑接口中遇到的各種疑難,主要涉及到的問題如下
- 運行的接口有多個(>=2)其中有一個前提是必須登錄才能進行其他接口的操作,但是登錄不想每次都運行,該怎么解決呢,請往下看~
- 批量執行接口的過程中,需要不同的參數運行接口,使用到了csv參數化
- 接口結束之后,需要對響應結果中的一部分信息保留進行數據對比
進入正題,先來解決第一個問題,登錄接口只需要運行一次即可,然后其他接口可以使用登錄響應結果中的token值進行接口操作。這里jmeter提供了setUp線程可以解決這個問題。
首先在jmeter計划中添加一個線程setUp,把登錄接口放置到setUp線程中,然后使用json提取器獲取到token信息,並把token信息保存為jmeter變量,如圖
登錄的響應結果信息如下
{
"access_token":"dc1dcb1f-725e-4b17-9f47-e1d97477ba11",
"token_type":"bearer",
"refresh_token":"307cee12-973e-44af-8022-63949b2c3bd5",
"expires_in":899,
"scope":"READ WRITE"
}
這里主要使用json提取器來獲取token的變量信息
根據響應結果,使用json提取器,主要用$.access_token
提取變量。
然后使用Beanshell后置處理器,將變量保存為jmeter系統變量,代碼如下
${__setProperty(all_token,${access_token},false)}
如圖
跨線程的其他線程組怎么使用這個變量access_token呢,可以使用http信息頭管理器來實現,在http信息頭管理器中,添加Authorization來實現,如圖
Authorization Bearer ${__property(all_token,,)}
至此第一個問題已經解決了,那么接下來就是第二個接口的參數化操作了。
這里主要使用了csv進行參數化
csv文本參數信息如圖
參數化文本已經准備好了,接下來就是在jmeter中添加csv數據文件設置,如圖
說明:
-
文件名稱:參數化的csv文件
-
文件編碼:默認可以不填,這里因為有中文,所以使用gb2312,可以根據實際情況設置utf-8或其他
-
變量名稱:這里設置的變量名稱在接口中會使用這個變量信息,所以一定要慎重
如圖上所標識,這里的變量名稱必須一致。
到這里,已經完成了csv的參數化,那么我們如果獲取響應的結果呢?
先來看一下相應的結果的結構是什么吧~
[
{
"properties":{
"cal_name":"雲耳",
"e_type":"food",
"end_index":12,
"food_id":8457,
"kcal_unit_weight":37.95,
"name":"雲耳",
"start_index":10,
"time_stamp":1566544101
},
"sub_properties":{
"grams":30,
"is_default":true,
"quantifier_id":57,
"quantity":1,
"unit":"朵"
},
"type":"Entity"
},
{
"properties":{
"cal_name":"黑木耳",
"e_type":"food",
"end_index":9,
"food_id":8456,
"kcal_unit_weight":37.95,
"name":"黑木耳",
"start_index":6,
"time_stamp":1566544101
},
"sub_properties":{
"grams":30,
"is_default":true,
"quantifier_id":57,
"quantity":1,
"unit":"朵"
},
"type":"Entity"
},
{
"properties":{
"cal_name":"木耳",
"e_type":"food",
"end_index":2,
"food_id":5593,
"kcal_unit_weight":37.95,
"name":"木耳",
"start_index":0,
"time_stamp":1566544101
},
"sub_properties":{
"grams":30,
"is_default":true,
"quantifier_id":57,
"quantity":1,
"unit":"朵"
},
"type":"Entity"
}
]
當然還可以使用json提取器,來獲取變量信息的,使用$[*].properties.cal_name;$[*].properties.name
,兩個變量之前使用;分開,如圖所示
根據之前的使用BeanShell斷言判斷請求返回的Json相應結果(不同json格式整理)了解到可以使用BeanShell來獲取響應結果的變量。
好了,那么接下來就是如何保保存響應結果中需要的信息到csv文本中了。
jmeter中beanshell提供了寫入csv文件的方法,主要代碼如下
//保存的本地文件
FileWriter fo = new FileWriter("E:\\test\\result_jm.csv",true);
BufferedWriter out = new BufferedWriter(fo);
//需要保存的字段信息
out.write(vars.get("cal")+":"+vars.get("name")+",");
//每個信息完成之后需要換行
out.write(System.getProperty("line.separator"));
out.close();
fo.close();
這里想實現的主要是:對於響應結果非空的數據則保存響應結果到文件1,而對於響應結果為空,則只需要保存輸入的參數信息到文件2,以便后期對比確認接口數據准確度。
完整代碼如下
import org.json.*;
import org.json.JSONObject;
import org.json.JSONAarry;
//設置文件編碼
prev.setDataEncoding("UTF-8");
int i=0;
try{
log.info("響應結果中的cal_name是"+vars.get("cal"));
//獲取json提取器中的變量cal
//String cal_test = vars.get("cal");
String response_data = prev.getResponseDataAsString();//獲取請求返回值,此處獲取到String類型;
//JSONObject data_obj = new JSONObject(response_data);//將string類型的返回值構建成JSONObject對象
//JSONArray data_array = response_data.getJSONArray[0];//返回結果是數組
JSONArray data_array = new JSONArray(response_data);
int len = data_array.length();//獲取data數組的長度
String strlen = Integer.toString(len);
log.info("響應結果字符串長度是"+strlen);
String str_array = data_array.toString();
log.info("響應結果字符串是:"+str_array);
//cal_test str_array == null ;cal_test.length() !=null;str_array.equals(0)
if(len==0){
log.info("*****************食物匹配失敗********************");
//如果響應結果為空,則只保存food名字到本地文件
FileWriter fos = new FileWriter("E:\\test\\HB\\food_result2_jm.csv",true);
BufferedWriter outs = new BufferedWriter(fos);
outs.write(vars.get("food")+",");
log.info("原來的食譜名稱是:"+ vars.get("food"));
outs.write(System.getProperty("line.separator"));
outs.close();
fos.close();
}else{
log.info("*************響應結果中獲取食物cal和name****************");
for(i=0;i<len;i++){
//返回數組
JSONObject object = data_array.getJSONObject(i);
//只獲取響應結果中第一個properites的信息,需要取得多個properties,則可以使用for循環
JSONObject temp_properties = (JSONObject)object.getJSONObject("properties");
//只獲取響應結果中properties中的calname值
cal_name_string = temp_properties.getString("cal_name");
log.info("Beanshell 后置處理器的提取的響應cal_name響應結果是:"+ cal_name_string);
//保存響應結果中的cal_name變量
vars.put("cal_name_string",cal_name_string);
name_string = temp_properties.getString("name");
log.info("Beanshell 后置處理器的提取的響應name_string響應結果是:"+ name_string);
//保存響應結果中的cal_name變量
vars.put("name_string",name_string);
log.info("*************食物匹配有結果****************");
//保存的本地文件,保存響應結果非空的數據
FileWriter fo = new FileWriter("E:\\test\\HB\\food_result1_jm.csv",true);
BufferedWriter out = new BufferedWriter(fo);
out.write(vars.get("name_string")+":"+vars.get("cal_name_string")+":"+vars.get("food")+",");
log.info("響應結果中食物名稱是:"+ vars.get("cal_name_string"));
log.info("響應結果中食物名稱是:"+ vars.get("name_string"));
log.info("原來的食譜名稱是:"+ vars.get("food"));
out.write(System.getProperty("line.separator"));
out.close();
fo.close();
}
}
//JSONObject object = data_array.getJSONObject(0);
//log.info(object);
//String cal_test = object.getString("cal_name");
}
catch(Throwable ex){
log.error("Failed in Beanshell",ex);
throw ex;
// //如果響應結果為空,則只保存food名字到本地文件
// FileWriter fos = new FileWriter("E:\\test\\HB\\food_result2_jm.csv",true);
// BufferedWriter outs = new BufferedWriter(fos);
// outs.write(vars.get("food")+",");
// log.info(vars.get("food"));
// outs.write(System.getProperty("line.separator"));
//
// outs.close();
// fos.close();
}
這里使用到了json包,提供一個下載地址:https://repo1.maven.org/maven2/org/json/json/20190722/
ok,到這里jmeter一個完整的流程就結束了,這里有部分jmeter的結果信息,如下
2019-08-23 15:08:28,064 INFO o.a.j.t.JMeterThread: Thread is done: chatbot 1-2628
2019-08-23 15:08:28,064 INFO o.a.j.t.JMeterThread: Thread finished: chatbot 1-2628
2019-08-23 15:08:28,065 INFO o.a.j.u.BeanShellTestElement: 響應結果字符串長度是1
2019-08-23 15:08:28,065 INFO o.a.j.u.BeanShellTestElement: 響應結果字符串是:[{"sub_properties":{"unit":"杯","quantifier_id":32,"quantity":1,"grams":250,"is_default":true},"type":"Entity","properties":{"start_index":0,"time_stamp":1566544108,"cal_name":"野菊","name":"野菊","end_index":2,"kcal_unit_weight":46.8,"food_id":5559,"e_type":"food"}}]
2019-08-23 15:08:28,065 INFO o.a.j.u.BeanShellTestElement: *************響應結果中獲取食物cal和name****************
2019-08-23 15:08:28,065 INFO o.a.j.u.BeanShellTestElement: Beanshell 后置處理器的提取的響應cal_name響應結果是:野菊
2019-08-23 15:08:28,065 INFO o.a.j.u.BeanShellTestElement: Beanshell 后置處理器的提取的響應name_string響應結果是:野菊
2019-08-23 15:08:28,065 INFO o.a.j.u.BeanShellTestElement: *************食物匹配有結果****************
2019-08-23 15:08:28,067 INFO o.a.j.u.BeanShellTestElement: 響應結果中食物名稱是:野菊
2019-08-23 15:08:28,067 INFO o.a.j.u.BeanShellTestElement: 響應結果中食物名稱是:野菊
2019-08-23 15:08:28,067 INFO o.a.j.u.BeanShellTestElement: 原來的食譜名稱是:野菊(鮮)
...
2019-08-23 15:08:30,407 INFO o.a.j.t.JMeterThread: Thread is done: chatbot 1-2690
2019-08-23 15:08:30,407 INFO o.a.j.t.JMeterThread: Thread finished: chatbot 1-2690
2019-08-23 15:08:30,522 INFO o.a.j.u.BeanShellTestElement: 響應結果中的cal_name是竹參
2019-08-23 15:08:30,524 INFO o.a.j.u.BeanShellTestElement: 響應結果字符串長度是3
2019-08-23 15:08:30,524 INFO o.a.j.u.BeanShellTestElement: 響應結果字符串是:[{"sub_properties":{"unit":"份","quantifier_id":18,"quantity":1,"grams":200,"is_default":true},"type":"Entity","properties":{"start_index":8,"time_stamp":1566544110,"cal_name":"竹參","name":"竹參","end_index":10,"kcal_unit_weight":155,"food_id":12628,"e_type":"food"}},{"sub_properties":{"unit":"份","quantifier_id":18,"quantity":1,"grams":200,"is_default":true},"type":"Entity","properties":{"start_index":5,"time_stamp":1566544110,"cal_name":"干竹笙","name":"竹笙","end_index":7,"kcal_unit_weight":312.116,"food_id":10653,"e_type":"food"}},{"sub_properties":{"unit":"片","quantifier_id":34,"quantity":1,"grams":7,"is_default":true},"type":"Entity","properties":{"start_index":0,"time_stamp":1566544110,"cal_name":"竹蓀","name":"竹蓀","end_index":2,"kcal_unit_weight":155,"food_id":5607,"e_type":"food"}}]
2019-08-23 15:08:30,524 INFO o.a.j.u.BeanShellTestElement: *************響應結果中獲取食物cal和name****************
2019-08-23 15:08:30,524 INFO o.a.j.u.BeanShellTestElement: Beanshell 后置處理器的提取的響應cal_name響應結果是:竹參
2019-08-23 15:08:30,524 INFO o.a.j.u.BeanShellTestElement: Beanshell 后置處理器的提取的響應name_string響應結果是:竹參
2019-08-23 15:08:30,524 INFO o.a.j.u.BeanShellTestElement: *************食物匹配有結果****************
2019-08-23 15:08:30,526 INFO o.a.j.u.BeanShellTestElement: 響應結果中食物名稱是:竹參
2019-08-23 15:08:30,526 INFO o.a.j.u.BeanShellTestElement: 響應結果中食物名稱是:竹參
2019-08-23 15:08:30,526 INFO o.a.j.u.BeanShellTestElement: 原來的食譜名稱是:竹蓀(干)竹笙、竹參
2019-08-23 15:08:30,526 INFO o.a.j.u.BeanShellTestElement: Beanshell 后置處理器的提取的響應cal_name響應結果是:干竹笙
2019-08-23 15:08:30,526 INFO o.a.j.u.BeanShellTestElement: Beanshell 后置處理器的提取的響應name_string響應結果是:竹笙
2019-08-23 15:08:30,526 INFO o.a.j.u.BeanShellTestElement: *************食物匹配有結果****************
2019-08-23 15:08:30,527 INFO o.a.j.u.BeanShellTestElement: 響應結果中食物名稱是:干竹笙
2019-08-23 15:08:30,527 INFO o.a.j.u.BeanShellTestElement: 響應結果中食物名稱是:竹笙
2019-08-23 15:08:30,527 INFO o.a.j.u.BeanShellTestElement: 原來的食譜名稱是:竹蓀(干)竹笙、竹參
2019-08-23 15:08:30,527 INFO o.a.j.u.BeanShellTestElement: Beanshell 后置處理器的提取的響應cal_name響應結果是:竹蓀
2019-08-23 15:08:30,527 INFO o.a.j.u.BeanShellTestElement: Beanshell 后置處理器的提取的響應name_string響應結果是:竹蓀
2019-08-23 15:08:30,527 INFO o.a.j.u.BeanShellTestElement: *************食物匹配有結果****************
2019-08-23 15:08:30,528 INFO o.a.j.u.BeanShellTestElement: 響應結果中食物名稱是:竹蓀
2019-08-23 15:08:30,528 INFO o.a.j.u.BeanShellTestElement: 響應結果中食物名稱是:竹蓀
2019-08-23 15:08:30,528 INFO o.a.j.u.BeanShellTestElement: 原來的食譜名稱是:竹蓀(干)竹笙、竹參
2019-08-23 15:08:30,528 INFO o.a.j.t.JMeterThread: Thread is done: chatbot 1-2685
2019-08-23 15:08:30,528 INFO o.a.j.t.JMeterThread: Thread finished: chatbot 1-2685
2019-08-23 15:08:30,529 INFO o.a.j.e.StandardJMeterEngine: Notifying test listeners of end of test
2019-08-23 15:08:30,529 INFO o.a.j.s.FileServer: Close: E:\test\HB\qa.csv
2019-08-23 15:08:30,529 INFO o.a.j.s.FileServer: Close: E:\test\HB\food_jm.csv
2019-08-23 15:08:30,529 INFO o.a.j.g.u.JMeterMenuBar: setRunning(false, *local*)
總結:以上就是jmeter接口測試所遇到的問題以及如何解決的~,這里還有一點小問題,因為參數化的時候,是中文信息,所以開始的時候一直都是亂碼,這里說一下有幾個辦法,給大家一個參考。
第一個方法:修改jmeter.properties文件中的編碼格式為utf-8sampleresult.default.encoding=UTF-8
第二個方法,接口信息中設置編碼格式為utf-8,如圖
第三個方法:在beanshell中設置編碼格式為utf-8,//設置文件編碼
prev.setDataEncoding("UTF-8");
還有可能不是編碼格式的問題,而是字體支持的原因,可以修改jmeter.properties中的jsyntaxtextarea.font.family=宋體
可以試試看看能不能解決。