Jmeter二次開發——自定義函式
阿新 • • 發佈:2021-01-22
在之前的博文中,[Jmeter二次開發——基於Java請求](https://www.cnblogs.com/hong-fithing/p/14098210.html),已介紹了Jmeter二次開發的基礎情況,上次分享的是java請求開發,今天來分享下Jmeter中的函式開發。聊到Jmeter的函式,知道Jmeter使用的博友肯定很熟悉。Jmeter自帶一個函式庫,有很多的函式,比如:__P,__Random,函式助手給我們提供了很多的方便之處。函式助手使用如下所示:
![](https://img2020.cnblogs.com/blog/1242227/202101/1242227-20210122152045166-20653936.png)
但有些時候,自帶的函式滿足不了真實的測試場景,比如:生成隨機手機號。常規做法,應該是設定手機號區號的固定值,再通過__Random函式生成8位隨機數,從而拼接成一個手機號,這樣的做法的確可以滿足,但要想手機號的區段也是隨機的呢,是不是就不太好處理了。那就用函式二次開發試試。
## 函式二次開發
### 建立以functions結尾的包
這個是特別需要注意點,以.functions結尾,正常建立包即可。
### 類繼承AbstractFunction
二次開發時,新建的類,需要繼承AbstractFunction,這個也是需要注意的。至於為什麼需要繼承AbstractFunction,看原始碼就能明白,原始碼如下所示:
```
public abstract class AbstractFunction implements Function {
public AbstractFunction() {
}
public abstract String execute(SampleResult var1, Sampler var2) throws InvalidVariableException;
public String execute() throws InvalidVariableException {
JMeterContext context = JMeterContextService.getContext();
SampleResult previousResult = context.getPreviousResult();
Sampler currentSampler = context.getCurrentSampler();
return this.execute(previousResult, currentSampler);
}
public abstract void setParameters(Collection var1) throws InvalidVariableException;
public abstract String getReferenceKey();
protected JMeterVariables getVariables() {
return JMeterContextService.getContext().getVariables();
}
protected void checkParameterCount(Collection parameters, int min, int max) throws InvalidVariableException {
int num = parameters.size();
if (num > max || num < min) {
throw new InvalidVariableException(this.getReferenceKey() + " called with wrong number of parameters. Actual: " + num + (min == max ? ". Expected: " + min + "." : ". Expected: >= " + min + " and <= " + max));
}
}
protected void checkParameterCount(Collection parameters, int count) throws InvalidVariableException {
int num = parameters.size();
if (num != count) {
throw new InvalidVariableException(this.getReferenceKey() + " called with wrong number of parameters. Actual: " + num + ". Expected: " + count + ".");
}
}
protected void checkMinParameterCount(Collection parameters, int minimum) throws InvalidVariableException {
int num = parameters.size();
if (num < minimum) {
throw new InvalidVariableException(this.getReferenceKey() + " called with wrong number of parameters. Actual: " + num + ". Expected at least: " + minimum + ".");
}
}
protected final void addVariableValue(String value, CompoundVariable[] values, int index) {
if (values.length > index) {
String variableName = values[index].execute().trim();
if (StringUtils.isNotEmpty(variableName)) {
JMeterVariables vars = this.getVariables();
if (vars != null) {
vars.put(variableName, value);
}
}
}
}
}
```
### 引數解釋
#### getArgumentDesc()
獲取介面所要顯示的引數說明
#### execute()
函式的主體業務
#### getReferenceKey()
獲取函式的名稱
#### setParameters()
設定引數,接收使用者傳遞的引數
#### checkParameterCount()
檢測引數數量是否準確
### 函式開發
#### 獲取函式的名稱
名稱自定義,如下所示:
```
private static final String key = "__XXX";
```
這裡需要注意的是:函式開頭是以2個下劃線開頭。
名稱定義好了,那如何獲取呢?就用我們剛才說的方法獲取即可,如下所示:
```
@Override
public String getReferenceKey() {
return key;
}
```
#### 獲取介面所要顯示的引數說明
在Jmeter的函式助手中,對應函式都有對應的引數說明,如下所示:
![](https://img2020.cnblogs.com/blog/1242227/202101/1242227-20210122164937485-503998315.png)
那如何配置能實現呢?程式碼如下:
```
private final static List args = new LinkedList();
static{
args.add("介面引數");
}
```
如果有多個引數怎麼辦?多個引數,多個args.add即可
獲取引數名稱,同樣用剛才介紹的方法獲取即可,如下所示:
```
@Override
public List getArgumentDesc() {
return args;
}
```
#### 獲取引數值
```
@Override
public void setParameters(Collection args0) throws InvalidVariableException {
//檢測使用者呼叫函式時,檢查引數個數,個數不對則報錯
checkParameterCount(args0,3);
Object[] params = args0.toArray();
//轉換隻為string
telNum = ((CompoundVariable)params[0]).execute();
start = ((CompoundVariable)params[1]).execute();
end = ((CompoundVariable)params[2]).execute();
}
```
獲取引數值中,可以檢測函式的入參個數是否準確,不準確則會報錯,報錯資訊如下所示:
![](https://img2020.cnblogs.com/blog/1242227/202101/1242227-20210122165947622-774597245.png)
#### 函式的主體業務
介紹到這,就是函式的核心內容了,該函式要實現什麼功能,就是在該方法中處理,示例程式碼如下所示:
```
@Override
public String execute(SampleResult sampleResult, Sampler sampler) throws InvalidVariableException {
SampleResult sampleResult1 = new SampleResult();
try {
sampleResult1.sampleStart();
int index=getNum(0,telFirst.length-1);
String telNum = telFirst[index];
String two = String.valueOf(getNum(1, 888) + 10000).substring(1);
String three = String.valueOf(getNum(1, 9100) + 10000).substring(1);
tel = telNum + two + three;
logger.info("手機號區段:"+ telNum +" 隨機生成的手機號是:" + tel);
if (varName != null) {
JMeterVariables vars = getVariables();
final String varTrim = varName.execute().trim();
if (vars != null && varTrim.length() > 0) {
vars.put(varTrim, telNum);
}
}
sampleResult1.setResponseData("手機號區段:"+ telNum +" 隨機生成的手機號是:" + tel,"utf-8");
sampleResult1.setSuccessful(true);
}catch (Exception e){
sampleResult.setSuccessful(false);
e.printStackTrace();
}finally {
sampleResult1.sampleEnd();
}
return tel;
}
```
## 程式碼除錯
寫到這裡,基本完成了,但還是得測試下,功能是否正常,如果先打jar包,丟到Jmeter中,發現有bug的話,來來回回處理,就折騰了,所以還是需要先測試下的。
在test下新建測試類,示例程式碼如下所示:
```
import org.junit.Test;
public class Function_Test {
@Test
public void phoneTest() throws Exception {
RandomPhoneJmeterFunctions randomPhone= new RandomPhoneJmeterFunctions();
String phoneString = randomPhone.execute();
System.out.println("隨機手機號:" + phoneString);
}
}
```
測試程式碼很簡單,執行測試類,沒有報錯並打印出手機號,則說明沒有問題。執行後的結果如下所示:
![](https://img2020.cnblogs.com/blog/1242227/202101/1242227-20210122180044366-490570793.png)
## 生成jar包
生成jar包就不重複講了,可以看以前的博文,[IDEA的基本操作——匯入匯出jar包](https://www.cnblogs.com/hong-fithing/p/13964449.html)
## Jmeter中使用
程式碼寫好後,自然是要在jmeter中驗證下功能的,我們將生成的jar包放到jmeter的\lib\ext資料夾下,如果jmeter已啟用,則需要重啟哦,不然不會生效。
開啟jmeter後,使用函式助手,看新開發的函式是否有展示,如下所示:
![](https://img2020.cnblogs.com/blog/1242227/202101/1242227-20210122181050377-1591006798.png)
生成函式變數,操作如下所示:
![](https://img2020.cnblogs.com/blog/1242227/202101/1242227-20210122181029189-1095660490.png)
新建執行緒組,並新增http請求,驗證碼生成的手機號是不是隨機的,執行後,檢視結果樹,如下所示:
![](https://img2020.cnblogs.com/blog/1242227/202101/1242227-20210122181304223-1223851319.png)
也可以通過日誌檢視,開發的時候,加了響應日誌,如下所示:
![](https://img2020.cnblogs.com/blog/1242227/202101/1242227-20210122181452843-920053284.png)
到此,就說明功能沒問題了。函式開發按上述步驟就可以完成,遇到不滿足測試場景的時候,就可以自己diy一個了。
最後附上完整程式碼,如下所示:
```
private static Logger logger = LogManager.getLogger(RandomPhoneJmeterFunctions.class.getName());
private String tel;
//定義函式名稱
private static final String KEY = "__RandomPhone";
//定義函式介面顯示的引數名稱
private static final List desc = new LinkedList();
static{
desc.add("介面引數");
}
private static final String[] telFirst = "134,135,136,137,138,139,150,151,152,157,158,159,130,131,132,155,156,133,153 ".split(",");
private CompoundVariable varName;
//業務主邏輯
@Override
public String execute(SampleResult sampleResult, Sampler sampler) throws InvalidVariableException {
SampleResult sampleResult1 = new SampleResult();
try {
sampleResult1.sampleStart();
int index=getNum(0,telFirst.length-1);
String telNum = telFirst[index];
String two = String.valueOf(getNum(1, 888) + 10000).substring(1);
String three = String.valueOf(getNum(1, 9100) + 10000).substring(1);
tel = telNum + two + three;
logger.info("手機號區段:"+ telNum +" 隨機生成的手機號是:" + tel);
if (varName != null) {
JMeterVariables vars = getVariables();
final String varTrim = varName.execute().trim();
if (vars != null && varTrim.length() > 0) {
vars.put(varTrim, telNum);
}
}
sampleResult1.setResponseData("手機號區段:"+ telNum +" 隨機生成的手機號是:" + tel,"utf-8");
sampleResult1.setSuccessful(true);
}catch (Exception e){
sampleResult.setSuccessful(false);
e.printStackTrace();
}finally {
sampleResult1.sampleEnd();
}
return tel;
}
//獲取引數值
@Override
public void setParameters(Collection args0) throws InvalidVariableException {
//檢測使用者呼叫函式時,檢測引數個數
checkParameterCount(args0,1);
Object[] params = args0.toArray();
if (params.length > 0) {
varName = (CompoundVariable) params[0];
} else {
varName = null;
}
}
//獲取函式的名稱
@Override
public String getReferenceKey() {
return KEY;
}
//獲取介面所要顯示的引數說明
@Override
public List getArgumentDesc() {
return desc;
}
private static int getNum(int start,int end)
{
return (int)(Math.random()*(end-1));