做網(wǎng)站加模塊今日熱榜
JMeter高級使用
案例:
- 用戶登錄后-選擇商品-添加購物車-創(chuàng)建訂單-驗證結(jié)果
問題:
- JMeter測試中,驗證結(jié)果使用斷言,但斷言都是固定的內(nèi)容
- 假如要判斷的內(nèi)容(預(yù)期內(nèi)容)是在變化的, 有時候還是不確定的, 那該怎么辦呢?
解決:
- 1.通過查詢數(shù)據(jù)庫獲取動態(tài)的結(jié)果
- 2.使用beanshell斷言進行結(jié)果驗證
實現(xiàn)步驟:
-
創(chuàng)建登錄接口HTTP請求
-
創(chuàng)建添加購物車接口HTTP請求
-
創(chuàng)建訂單接口HTTP請求,通過數(shù)據(jù)查看訂單號
-
對訂單接口結(jié)果驗證,是否創(chuàng)建訂單號
-
查詢數(shù)據(jù)庫獲取結(jié)果
-
使用beanshell斷言進行動態(tài)結(jié)果驗證
-
1. JMeter連接數(shù)據(jù)庫
1.1 數(shù)據(jù)庫配置信息
配置信息:
- ip:192.168.1.242
- port:7090
- 用戶名:test
- 密碼:test123456
- 數(shù)據(jù)庫名稱:xxxx
可使用數(shù)據(jù)庫連接工具進行連接,例如:navicat
1.2 連接數(shù)據(jù)庫
- 元件
JDBC Connection Configuration
進行連接數(shù)據(jù)庫
實現(xiàn)步驟:
-
1.下載MySQL的jdbc驅(qū)動(mysql-connector-java.jar)
- https://mvnrepository.com/artifact/mysql/mysql-connector-java
- 將其放到放在指定的目錄,或者放在 …\apache-jmeter\lib\ 目錄下
- https://mvnrepository.com/artifact/mysql/mysql-connector-java
-
在測試計劃下添加驅(qū)動地址
-
-
備注:
- 如果放在jmeter/bin目錄,則不需要在測試計劃下添加jar包
-
-
選擇線程組-添加-配置原件-JDBC Connection Configuration
-
主要配置
- Variable Name Bound to Pool
- 配置變量名稱
- Variable Name不能為空
- Database connection
- DataBase URL 格式為:jdbc:mysql://服務(wù)器ip:端口號/數(shù)據(jù)庫
- 在數(shù)據(jù)庫后加參數(shù)?allowMultiQueries=true,可同時執(zhí)行多條mysql語句;否則報錯
- select語句中含有中文字符的緣故,jmeter識別不了。
- 解決辦法:就是在JDBC 的連接中,增加useUnicode=true&characterEncoding=utf8
- Variable Name Bound to Pool
-
jdbc:mysql://211.103.136.242:7090/db-name test test123456
-
-
添加JDBC Request
- 添加-> 取樣器-> JDBC Request
- 添加變量和查詢語句
- 變量名必須和JDBC Connection Configuration中的變量名保持一致
- 添加-> 取樣器-> JDBC Request
-
-
查詢語句
-
select order_id from tb_order_info where user_id='1' order by order_id desc limit 3
-
-
Variable names:將查詢結(jié)果當做一個參數(shù)使用
-
查出來的數(shù)據(jù)有好些內(nèi)容,調(diào)用方式
``` 取數(shù)據(jù)第1值調(diào)用:$ {test_01} 取數(shù)據(jù)第5值調(diào)用:$ {test_05} 取數(shù)據(jù)第n值調(diào)用:$ {test_n}
2. Beanshell使用
2.1 介紹
什么是Bean Shell?
-
BeanShell是一種完全符合Java語法規(guī)范的腳本語言,并且又擁有自己的一些語法和方法;
-
BeanShell是一種松散類型的腳本語言(這點和JS類似);
-
BeanShell是用Java寫成的,一個小型的、免費的、可以下載的、嵌入式的Java源代碼解釋器,具有對象腳本語言特性,非常精簡的解釋器jar文件大小為175k。
-
BeanShell執(zhí)行標準Java語句和表達式,另外包括一些腳本命令和語法。
官網(wǎng):http://www.BeanShell.org/
JMeter中用BeanShell的好處
- JMeter也是由java編寫的,而java運行時需要先編譯,然后才可以運行
- 而BeanShell是一款解釋器,直接可能運行源代碼
BeanShell在JMeter的作用
- 對JMeter的功能的擴展
- 對jmeter變量的一些操作
2.2 Jmeter有哪些BeanShell
- 定時器: BeanShell Timer
- 前置處理器:BeanShell PreProcessor
- 取樣器: BeanShell Sampler
- 后置處理器:BeanShell PostProcessor
- 斷言: BeanShell斷言
- 監(jiān)聽器: BeanShell Listener
備注:
- 一般歸屬于線程組或邏輯控制器,相對獨立
- 而BeanShell PreProcessor和BeanShell PostProcessor歸屬于sampler(取樣器)
- 前者是固定在sampler運行前運行
- 后者是在sampler運行后運行,二者都依賴于sampler而存在
- BeanShell斷言同樣依賴于sampler,作用是斷言sampler是否成功
應(yīng)用場景:
- 生成變量
- 解析響應(yīng)結(jié)果
- 定制化邏輯處理
- Beanshell還常用于請求發(fā)送前后的加密解密
2.3 Bean Shell常用內(nèi)置變量
JMeter在它的BeanShell中內(nèi)置了變量,用戶可以通過這些變量與JMeter進行交互,其中主要的變量
-
log
- 打印日志
-
ctx
- 該變量引用了當前線程的上下文
-
vars - (JMeterVariables)
- 操作jmeter變量
-
props - (JMeterProperties)
- 操作jmeter屬性,該變量引用了JMeter的配置信息,可以獲取Jmeter的屬性
-
prev - (獲取sample返回的信息)
- 獲取前面的sample返回的信息
-
Response
- 獲取Response對象,能通過這個對象獲取響應(yīng)信息
-
Failure
- 查看接口調(diào)使用能否成功,假如返回false是成功的,true是失敗的
-
FailureMessage
- 失敗信息,沒有設(shè)置的時候失敗信息是空的,可自定義相關(guān)信息
-
ResponseCode
- 返回接口code成功是200
-
SampleLabel
- 獲取接口請求的名稱
-
SamplerData
- 獲取請求的url和body
備注:
- 變量只對當前線程組有效,屬性是全局的。變量和屬性的值只能是字符串。
2.4 內(nèi)置變量詳解介紹
2.4.1 log
介紹
- 用于打印日志,最常用,也最簡單;
- 打印在 jmeter.log 中,可以設(shè)置打印級別,可以打印字符串、變量等。
使用方法
參考:http://excalibur.apache.org/apidocs/org/apache/log/Logger.html
-
打印 info 形式的普通字符串日志:
log.info("hello world"); #輸出 hello world
-
拼接字符串和變量 (其中 token 是 jmeter 局部變量):
log.info("hello world" + "${token}"); #輸出 hello world 和 token 變量的拼接結(jié)果
-
打印自定義變量
str = "hello world"; log.info(str); #輸出 hello world
-
打印 error 形式的普通字符串日志,修改JMeter日志輸出級別,否則看不到
log.error("ERROR-ERROR");
備注:
- print() 打印日志
- print() 是在控制臺中輸出信息,log() 默認是在 jmeter.log 中輸出信息
- 日志文件在安裝路徑下bin\Jmeter.log中
?
2.4.2 vars
介紹
- 用于存取 jmeter 局部變量
- 通常用于存取字符串內(nèi)容,也可以存取對象;
使用方法
參考:http://jmeter.apache.org/api/org/apache/jmeter/threads/JMeterVariables.html
-
獲取變量
- vars.get()
-
String key = vars.get("name"); #獲取變量名為 name 的值,并保存在 key 中
-
保存變量
-
vars.put()
vars.put("name","value"); #把變量 name(值為 value)保存到j(luò)meter變量中
-
-
對象保存JMeter變量中
-
vars.putObject()
vars.putObject("Object_name",new Object()); 把對象Object_name保存到j(luò)meter變量中
-
-
變量刪除
-
vars.remove()
vars.remove("name"); #從jmeter變量中刪除name
-
print() 是在控制臺中輸出信息,log() 默認是在 jmeter.log 中輸出信息。
備注:
-
bean shell提供了一個內(nèi)置變量Parameters,來保存參數(shù)的集合
-
log.info(Parameters);
-
-
Parameters
-
#輸入${name1}${name2} #腳本 //打印 log.info("傳遞的參數(shù)列表"+Parameters); log.info("name1:"+bsh.args[0]);log.info("name2:"+bsh.args[1]); log.info("name3:"+bsh.args[2]); log.info("name3:"+bsh.args[3]); //獲取參數(shù)傳遞過來的值存在變量里 vars.put("v1","bsh.args[1]"); vars.put("v2","bsh_args[2]"); vars.put("v3","bsh_args[3]");log.info("v1:"); log.info("v2:"); log.info("v3:");
-
2.4.3 props
介紹:
- 設(shè)置 jmeter 全局的靜態(tài)變量;
使用方法:
-
獲取屬性變量
-
props.get
-
ymd = props.get("START.YMD"); #獲取屬性 START.YMD 的值(腳本啟動日期) #其中的 key 和 value 均是字符串形式;
-
-
存入全局屬性
-
props.put
-
props.put("token","12ddb123")
-
-
判斷某屬性是否存在, 返回布爾值
`props.containsKey(``"PROPERTY_NAME"``) `
- 判斷某項值是否存在,返回布爾值:
props.contains("PROPERTY_VALUE")
- 刪除某個值
props.remove("PROPERTY_NAME")
- 所有屬性以字符串形式表示
props.toString()
備注:
- 操作jmeter屬性,該變量引用了JMeter的配置信息,可以獲取Jmeter的屬性,它的使用方法與vars類似,但是只能put進去String類型的值,而不能是一個對象
- 變量只對當前線程組有效,屬性props是全局的
- 變量和屬性的值只能是字符串
2.4.4 ctx/prev
介紹:
- ctx當前線程的上下文信息
- prev等同于ctx.getPreviousResult,通過prev可以直接獲取前一個取樣器返回的信息
使用方法:
參考:ctx:http://jmeter.apache.org/api/org/apache/jmeter/threads/JMeterContext.html
參考:prev:http://jmeter.apache.org/api/org/apache/jmeter/samplers/SampleResult.html
- prev.getResponseDataAsString():獲取響應(yīng)信息
- prev.getResponseCode() :獲取響應(yīng)code
String response_data = prev.getResponseDataAsString();
log.info("res:"+response_data);
String response_code = prev.getResponseCode();
log.info("res_code:"+response_code);
2.4.5 其它
使用方法:
參考:http://jmeter.apache.org/api/org/apache/jmeter/samplers/Sampler.html其它
-
ResponseCode響應(yīng)碼
- 代碼:
ResponseCode = 500;
- 結(jié)果
-
ResponseMessage響應(yīng)結(jié)果
-
代碼
-
ResponseMessage="自定義返回結(jié)果"
-
結(jié)果
-
-
SampleResult
-
代碼
-
SampleResult.setResponseData("Hello world");
-
與ResponseMessage功能類似
-
-
IsSuccess設(shè)置返回是否成功
-
代碼
-
IsSuccess=false
-
結(jié)果
-
-
Label取樣器的名稱
log.info(Label);
-
Sample
通過sampler來訪問當前取樣器;
使用方法參考:http://jmeter.apache.org/api/org/apache/jmeter/samplers/Sampler.html
2.4.6 Beanshell線程共享變量
分析:
-
變量只對當前線程組有效,屬性是全局的
-
使用beanshell把變量設(shè)置為全局變量
線程共享變量
-
Beanshell取樣器設(shè)置全局屬性
-
使用函數(shù)助手
-
${__setProperty(authorizations,${token},)}
-
使用props
-
props.put("authorizations","${token}")
-
-
其它線程組通過
JWT ${__property(authorizations,,)}
-
HTTP響應(yīng)信息頭更新
- JWT ${__property(authorizations,)}
JMeter中線程間共享變量可以通過定義屬性值來完成,JMeter啟動時會讀取一些屬性文件,比如jmeter.properties、user.properties,這些屬性
值是可以增加的,也可以修改的,通過BeanShell可以對其進行更改。
以BeanShell Sampler為例,在其中通過props.put()來增加屬性,props.get()來獲取屬性。
在其它Sampler中,比如Java Sampler中通過 ${__property(【屬性名稱】,)}來獲取。
2.5 Beanshell
通過Beanshell Sampler,測試人員可以編寫一些特定邏輯生成的數(shù)據(jù),并且通過vars.get、vars.put 或者props.get、props.put 把相應(yīng)的變量傳遞到Jmeter腳本當中
vars.get(String,String) 可以獲取Jmeter中已經(jīng)生成的變量
vars.put(String,String) 可以創(chuàng)建和更新Jmeter變量
props.get(String,String) 可以獲取Jmeter中已經(jīng)生成的屬性
props.put(String,String) 可以創(chuàng)建和更新Jmeter屬性
vars和props的區(qū)別是前者是變量,只能在同一線程組內(nèi)傳遞,后者是屬性,可以在整個測試計劃中跨線程組傳遞。
beanshell參數(shù)詳解:
-
勾選每次調(diào)用前重置,里面定義的變量就會被重置。
-
腳本文件可以導入beanshell腳本
- 調(diào)用java文件
java源文件
public class Myclass
{public int add(int a, int b){return a + b;}
}
步驟:
- 在bean shel中通過source(“代碼路徑”)方法引入java,然后調(diào)用方法和java一樣,new一個class,再調(diào)用里面的add 方法
//引入java文件 source將一個bsh腳本讀到解釋器或運行在另一個解釋器
source("/TEST/Test.java");//絕對路徑
//調(diào)用方法,語法和java一樣
int res = new Test().add(1,2);
//保存變量
vars.put("add",res.toString());
-
引入外部class文件
直接把上例中的java文件編譯成class文件
用addClassPath(“D:\”)方法引入 class文件,在用import導入包及類,然后就可以像java一樣調(diào)用了
//引入class文件
addClassPath("/Users/wuyanhong/Desktop/提升小課/接口測試零基礎(chǔ)入門/代碼/");
//導入類名
import MyClass;
//調(diào)用
int res = new MyClass().add(1,2);
//保存變量
vars.put("add",res.toString());
//打印變量
log.info(vars.get("add"));
案例1:獲取當前時間格式為yyyy-MM-dd HH:mm:ss
下面舉例寫展示當前日期:開發(fā)給個接口需要傳遞當前時間格式為yyyy-MM-dd HH:mm:ss
import java.util.*;import java.text.*;Date d = new Date();DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String dateStr = df.format(d);vars.put("current_date",dateStr); //給jmeter添加一個變量,內(nèi)置變量
2.6 Beanshell斷言
BeanShell斷言可以使用beanshell腳本來執(zhí)行斷言檢查,可以用于更復雜的個性化需求,使用更靈活,功能更強大,但是要能夠熟練使用beanshell腳本。
在這里除了可以使用beanshell的內(nèi)置變量外,主要通過Failure和FailureMessage來設(shè)置斷言結(jié)果。
- Failure = false;-----表示斷言成功
- Failure = true;-----表示斷言失敗
- FailureMessage = “……”;-----自定義的失敗信息。
實現(xiàn)步驟:
-
在保存訂單接口下添加beanshell斷言
-
編寫斷言代碼
-
//數(shù)據(jù)庫的取值與接口正則取值比對 if("${db_order_id_1}".equals("${order_id}_1")) {Failure=false;System.out.println("OK"); } else { Failure=true;FailureMessage="不一致"; }
-
參數(shù)詳解:
- bsh.args[0],bsh.args是一個數(shù)組,里面保存的是beanshell【參數(shù)】輸入框中保存的變量
- 參數(shù):可以將其他元件中已經(jīng)定義的變量作為參數(shù)傳給beanshell腳本,傳入的參數(shù)被存在bsh.args數(shù)組中
- 腳本文件:可以從文件導入腳本,而不是直接寫。
- 腳本:直接編寫beanshell代碼
2.7 BeanShell PreProcessor
測試中接口請求參數(shù)大部分需要加密后請求,處理需要加密的參數(shù)就需要用到j(luò)meter中的前置處理器BeanShell PreProcessor
案例:實現(xiàn)登錄密碼加密并請求登錄接口
-
在eclipse寫好md5加密的代碼,然后打成jar包(選中該類點擊右鍵->Export->jar file)
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException;public class MD5 {public static String getMD5(String sourceStr) {try {MessageDigest md = MessageDigest.getInstance("MD5");//獲取MD5實例md.update(sourceStr.getBytes());//此處傳入要加密的byte類型值byte[] digest = md.digest();//此處得到的是md5加密后的byte類型值int i;StringBuilder sb = new StringBuilder();for (int offset = 0; offset < digest.length; offset++) {i = digest[offset];if (i < 0)i += 256;if (i < 16)sb.append(0);sb.append(Integer.toHexString(i));//通過Integer.toHexString方法把值變?yōu)?6進制}return sb.toString();} catch (NoSuchAlgorithmException e) {e.printStackTrace();return null;}}public static void main(String []args){String res = MD5.getMD5("123456");System.out.println(res);}}
-
把打好的jar包放到j(luò)meter目錄下的apache-jmeter目錄的lib\ext下;
-
添加前置處理器-BeanShell PreProcessor
-
編寫代碼
-
import boxuegu.MD5; String res = new MD5().getMD5("123456"); System.out.println(res); vars.put("md5_pwd",res.toString());
//把加密后的密碼存到j(luò)meter變量中,然后在http sampler中就可通過${}使用:
-
執(zhí)行測試
2.8 BeanShell PostProcessor
獲取響應(yīng)結(jié)果,關(guān)聯(lián)操作
下載解析jar包:https://mvnrepository.com/artifact/com.alibaba/fastjson/1.2.62
步驟:
- 獲取響應(yīng),把響應(yīng)結(jié)果轉(zhuǎn)為json對象
- 獲取響應(yīng)參數(shù),并打印斷言結(jié)果
- 設(shè)置變量
代碼:
//1.獲取響應(yīng),把響應(yīng)結(jié)果轉(zhuǎn)為json對象
String response_data = prev.getResponseDataAsString();
JSONObject data_obj = new JSONObject(response_data);
log.info("res:"+response_data);
//2.獲取響應(yīng)參數(shù),打印斷言結(jié)果
String name=data_obj.get("username").toString();
log.info("name:"+name);
vars.put("username",name);
//3.判斷結(jié)果
if(name.equals("python")){log.info("成功");
}
else
{ log.info("失敗");
}
總結(jié):
拓展:
beanshell中參數(shù)傳遞一般指的是先獲取到參數(shù),再傳遞參數(shù)。在beanshell中傳遞參數(shù)一般使用vars.put(key,value)方法。
注意:
1.vars.get()不能接收int參數(shù)
2.vars.put(key,value)中,key要用雙引號""括起來
3. 并發(fā)測試
- ”并發(fā)測試”理解為性能測試,但接口測試中并發(fā)測試僅關(guān)注于并發(fā)測試系統(tǒng)的返回結(jié)果是否正確
- 并不關(guān)心相關(guān)的性能指標,例如系統(tǒng)資料、服務(wù)器響應(yīng)時間等等
- 為了實現(xiàn)并發(fā),我們可以在需要壓力的地方設(shè)置集合點,每到輸入用戶名和密碼登錄時,所有的虛擬用戶都相互之間等一等,然后一起訪問
3.1 集合點
jmeter里面的集合點通過添加定時器同步定時器
啟動:
-
點擊線程組,右鍵點擊添加->定時器->同步定時器
用法:
-
模擬用戶組的數(shù)量:集合多少人再執(zhí)行請求(也就是執(zhí)行的線程數(shù))
注意:等同于設(shè)置為線程數(shù),一定要確保設(shè)置的值不大于它所在線程組包含的用戶數(shù) -
超時時間以毫秒為單位:指定人數(shù) 多少秒沒交集合到算超時(設(shè)置延遲時間以毫秒為單位)
- 注意:如果設(shè)置timeout in milliseconds為0,表示無超時時間,會一直等下去。
- 線程數(shù)量無法達到"Number of Simultaneous Users to Group by"中設(shè)置的值,那么Test將無限等待,除非手動終止。
-
如果希望定時器僅用于其中一個取樣器,則把該定時器作為子節(jié)點加入
-
如果是作用于多個,放置請求之前