Jmeter二次開發——自定義函數

在之前的博文中,Jmeter二次開發——基於Java請求,已介紹了Jmeter二次開發的基礎情況,上次分享的是java請求開發,今天來分享下Jmeter中的函數開發。聊到Jmeter的函數,知道Jmeter使用的博友肯定很熟悉。Jmeter自帶一個函數庫,有很多的函數,比如:__P,__Random,函數助手給我們提供了很多的方便之處。函數助手使用如下所示:

但有些時候,自帶的函數滿足不了真實的測試場景,比如:生成隨機手機號。常規做法,應該是設定手機號區號的固定值,再通過__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<CompoundVariable> var1) throws InvalidVariableException;

    public abstract String getReferenceKey();

    protected JMeterVariables getVariables() {
        return JMeterContextService.getContext().getVariables();
    }

    protected void checkParameterCount(Collection<CompoundVariable> 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<CompoundVariable> 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<CompoundVariable> 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的函數助手中,對應函數都有對應的參數說明,如下所示:

那如何配置能實現呢?代碼如下:

private final static List<String> args = new LinkedList<String>();

static{
      args.add("界面參數");
}

如果有多個參數怎麼辦?多個參數,多個args.add即可

獲取參數名稱,同樣用剛纔介紹的方法獲取即可,如下所示:

@Override
public List<String> getArgumentDesc() {
    return args;
}

獲取參數值

    @Override
    public void setParameters(Collection<CompoundVariable> 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();
  }

獲取參數值中,可以檢測函數的入參個數是否準確,不準確則會報錯,報錯信息如下所示:

函數的主體業務

介紹到這,就是函數的核心內容了,該函數要實現什麼功能,就是在該方法中處理,示例代碼如下所示:

    @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);
    }
}

測試代碼很簡單,運行測試類,沒有報錯並打印出手機號,則說明沒有問題。運行後的結果如下所示:

生成jar包

生成jar包就不重複講了,可以看以前的博文,IDEA的基本操作——導入導出jar包

Jmeter中使用

代碼寫好後,自然是要在jmeter中驗證下功能的,我們將生成的jar包放到jmeter的\lib\ext文件夾下,如果jmeter已啓用,則需要重啓哦,不然不會生效。

打開jmeter後,使用函數助手,看新開發的函數是否有展示,如下所示:

生成函數變量,操作如下所示:

新建線程組,並添加http請求,驗證碼生成的手機號是不是隨機的,運行後,查看結果樹,如下所示:

也可以通過日誌查看,開發的時候,加了響應日誌,如下所示:

到此,就說明功能沒問題了。函數開發按上述步驟就可以完成,遇到不滿足測試場景的時候,就可以自己diy一個了。

最後附上完整代碼,如下所示:

private static Logger logger = LogManager.getLogger(RandomPhoneJmeterFunctions.class.getName());

    private String tel;
    //定義函數名稱
    private static final String KEY = "__RandomPhone";
    //定義函數界面顯示的參數名稱
    private static final List<String> desc = new LinkedList<String>();
    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<CompoundVariable> 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<String> getArgumentDesc() {
        return desc;
    }

    private static int getNum(int start,int end)
    {
        return (int)(Math.random()*(end-1));
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章