• 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的libext文件夹下,如果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));
        }
    
  • 相关阅读:
    JavaScript indexOf() 方法 和 lastIndexOf() 方法
    JS处理四舍五入函数 toFixed(n)(可取小数点后n位)
    animate支持的css属性
    jquery 停止动画 stop的几种用法
    js动态创建style节点(js文件中添加css)
    在CSS中定义a:link、a:visited、a:hover、a:active顺序
    网站设计如何适合用户的操作习惯?
    mongoDB入门必读
    堆栈简析
    单例模式
  • 原文地址:https://www.cnblogs.com/hong-fithing/p/14252671.html
Copyright © 2020-2023  润新知