发布新日志

  • Jmeter如何更好的组织脚本结构进行接口测试

    2018-01-17 23:18:04

  • jmeter ---json几种读取方式,ArrayList循环读取

    2018-01-14 17:39:06

    https://www.cnblogs.com/nzg-noway/p/7490412.html


    在之前写过提取json数据格式的文章,这次对jmeter读取json数据格式进行整理。

      举例一个接口的response 格式如下:

    复制代码
    {
       "data" : {
          "device_vec" : [
             {
                "agent_version" : "9.7.0.2225",
                "android_id" : "e3d699cf01620531",
                "asset_number" : "",
                "description" : "89vUwdwfVydEjqNAANxM11c72ujdmn",
                "device_name" : "357568061882002",
                "email" : "1504487508089@tt.com",
                "encryption_log_count" : 0,
                "encryption_version" : "",
                "engine_version" : "9.715-1024",
                "firewall_log_count" : 0,
                "firewall_version" : "",
                "group_id" : "aa000000-0000-0000-0000-000000000000",
                "group_name" : "Default",
                "id" : "35756806-1882-0020-0000-000000000000",
                "imei" : "357568061882002",
                "inactive_reason" : 0,
                "install_time" : 1503642124,
                "last_connected_time" : 1504742375,
                "last_scan_time" : 1503642674,
                "meid" : "",
                "noncomp_reason" : "",
                "os_version" : "4.3",
                "pattern_version" : "2.437.00",
                "phone_number" : "",
                "platform_type" : 512,
                "policy_id" : 32,
                "policy_name" : "",
                "security_status" : 3,
                "status" : 3,
                "user_name" : "test1504487508089",
                "virus_log_count" : 26,
                "wtp_log_count" : 0
             },
             {
                "agent_version" : "2.0.0.1518",
                "android_id" : "",
                "asset_number" : "",
                "description" : "3dLAbTlj7UQoOiodnAjDrfX1iI0PCx",
                "device_name" : "Michael’s iPhone",
                "email" : "1504487508089@tt.com",
                "encryption_log_count" : 0,
                "encryption_version" : "",
                "engine_version" : "",
                "firewall_log_count" : 0,
                "firewall_version" : "",
                "group_id" : "aa000000-0000-0000-0000-000000000000",
                "group_name" : "Default",
                "id" : "6954500b4f14e50bd20634481ee2c6d9f17b4ee3",
                "imei" : "35 445006 267069 9",
                "inactive_reason" : 0,
                "install_time" : 1503641446,
                "last_connected_time" : 1503652862,
                "last_scan_time" : 1503641477,
                "meid" : "35445006267069",
                "noncomp_reason" : "",
                "os_version" : "10.3.2",
                "pattern_version" : "",
                "phone_number" : "",
                "platform_type" : 1024,
                "policy_id" : 6,
                "policy_name" : "",
                "security_status" : 1,
                "status" : 3,
                "user_name" : "test1504487508089",
                "virus_log_count" : 0,
                "wtp_log_count" : 0
             }
          ],
          "total_count" : 2
       },
       "error_code" : 1,
       "message" : "Success",
       "timestamp" : 1504765848
    }
    复制代码

     

    下面就对device_vec取角标2的agent_version 参数进行提取。

     

    方法一:Jmter Json插件,JSON Path Extractor 提取器。

    处理Json数据的方法是使用JMeter的插件,该插件可以使用JSONPath来获取JSON数据中特定位置的数据。类似于XML文件中的XPath,JSONPath可以使用简单的表达式来操作Json对象。JSON Path Extractor是一个开源的增加了post处理器的插件,可以将该插件的Lib文件拷贝到JMeter的lib目录下或者通过Jmeter UI界面的Options-->Plugins Manager下载json插件即可。

    可以使用如下的JSONPath进行描述:

    $.data.device_vec[1].agent_version

    在JMeter中,只需要从PostProcessor菜单中打开JSON Path Extractor然后输入变量名与默认值即可,如下所示:

    JSONPath表达式较短并且易于阅读,能够有效提高测试脚本的易维护性,该插件并不随着标准的JMeter一起安装。

     

    方法二:Jmter 正则表达式插件正则表达式提取

    JMeter安装了正则表达式插件之后,可以按照固定的格式从字符串中提取数据,而本例中正则表达式如下所示:

    "agent_version":"(.+?)"

    使用了该表达式之后会返回所有服从表达式的字符串,但是只有一个表达式是我们所关注的。可以使用1个组作为模板($1$),而2则会返回第二个数据。

     

     

     方法三:Jmter BeanShell提取器, BeanShell提取器

    借用了JMeter的对于BeanShell支持的特性,BeanShell是一个轻量级的面向Java的脚本语言。BeanShell Post Processor允许使用标准的Java语法来处理Json数据,使用方法如下图所示:

       1.写一个jsonpath读取代码如下:

    复制代码
    import java.util.LinkedHashMap;
    import com.jayway.jsonpath.JsonPath;
    import com.jayway.jsonpath.Predicate;
    import net.minidev.json.JSONArray;
    public static String readjson(String json, String jsonPath) {
        try{
            Object value = JsonPath.read(json, jsonPath, new Predicate[0]);
            if (value instanceof Integer) {
                    return value.toString();
                      }else if (value instanceof String) {
                     return value.toString();
             }else if (value instanceof Boolean){
                     return value.toString();
             }else if (value instanceof JSONArray) {
                JSONArray arr = (JSONArray)value;
                if(!arr.isEmpty()){return arr.toJSONString();}
                      return "";
                }else if (value instanceof LinkedHashMap){
                        return value.toString();
                  }else{
                        return  value.toString();
                      }
        }catch(Exception e){
            return "pathnotfound";
        }
    }
    复制代码

    然后使用此方法来读取json数据格式

     

    2.导入com.eclipsesource.json 方法直接读取json

    com.eclipsesource.json,源码下载路径如下 https://github.com/ralfstx/minimal-json,只需将源码打成jar包放到jmeter的lib/ext目录下即可

    com.eclipsesource.json 适用方法:http://static.javadoc.io/com.eclipsesource.minimal-json/minimal-json/0.9.3/com/eclipsesource/json/JsonObject.html

     

    3.如果是循环读取,那就要算出List的长度做循环---用jsonpath读取方式去循环取(前面的jsonpath方法不再贴)

     

    4.如果是循环读取,那就要算出List的长度做循环---用com.eclipsesource.json api 读取方式循环读

    如下:

     

     

     

    总结

    本文列举出了三种可用的从Json格式的返回值中提取数据的方法,正则表达式对于简单的Json格式的数据的快速标准化非常占优势。而JsonPath插件可以用于创建能够被维护修改的脚本,但是需要额外的插件安装工作。而最后的带JSON库的BeanShell确实非常详细并且依赖于Java语言的灵活性可以进行进一步的开发。


  • Jmeter对Json格式数据的三种处理方式

    2018-01-14 17:38:06


    https://www.jianshu.com/p/fe5b0d70b1b3

    Json 作为一种数据交换格式在网络开发,特别是 RESTful(Representational State Transfer)架构中应用得越来越广泛。Jmeter是一款很适合做接口和性能的测试工具,对于下面这一段Json 格式的响应报文我们可以在jmeter里面使用三种不同的方法来进行数据的抽取工作。

    {
    :   "code":"000000",
    :   "data":
    :   {
    :   :   "pageCount":"1",
    :   :   "prizeLists":
    :   :   [
    :   :   :   {
    :   :   :   :   "cellphoneNum":"134****0001",
    :   :   :   :   "prizeId":"1000005",
    :   :   :   :   "prizeName":"10元话费"
    :   :   :   },
    :   :   :   {
    :   :   :   :   "cellphoneNum":"134****0001",
    :   :   :   :   "prizeId":"1000007",
    :   :   :   :   "prizeName":"4元话费"
    :   :   :   }
    :   :   ],
    :   :   "totalCount":"2"
    :   },
    :   "msg":"成功"
    }
    

    1)使用正则表达式提取prizeName的第二个值
    在Sampler上面添加后置处理器-->正则表达式提取器,


    引用名称:其他地方引用提取值的变量名称,这里填写的是:prizeNameValue,具体的引用方式是${prizeNameValue}。
    正则表达式:提取内容的正则表达式【()表示提取,对于你要提前的内容需要用小括号括起来】。
    模板:用$$引用起来,如果在正则表达式中有多个提取表达式(多个括号括起来的部分),则可以是$1$,$2$等等,表示解析到的第几个值给prizeNameValue,正则表达式的提取模式,值从1开始,值0对应的是整个匹配的表达式。
    匹配数字(0代表随机):0代表随机,-1代表所有,其余正整数代表将在已提取的内容中第几个匹配的内容。这里需要提取的是第二个匹配的值。
    缺省值:正则匹配失败时取的值。
    可以在jmeter中添加Sampler -->Debug Sampler来看正则表达式的取值。


    从上图中可以看出提取到的prizeNameValue的值是4元话费。
    2)使用 JMeter 的插件JSONPath 来获取 JSON 数据中特定位置的数据
    在jmeter的plugins网站http://jmeter-plugins.org/downloads/all/ 选择 JMeterPlugins-ExtrasLibs-X.X.X.zip下载,解压以后将lib和lib/ext中的jar包放到jmeter安装目录对应位置,然后重启jmeter。
    在Sampler上面添加后置处理器-->jp@gc - JSON Path Extractor,


    在DebugSampler的结果中可以看到prizeNameJson的取值是4元话费。

    3)使用JMeter的BeanShell Post Processor来处理Json数据
    将fastjson.jar 拷贝到 jmeter lib 文件夹下后重启 jmeter
    在Sampler上面添加后置处理器-->BeanShell PostProcessor

    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.JSONObject;
    
    String json=prev.getResponseDataAsString();
    JSONObject jso = JSON.parseObject(json);
    JSONObject data = jso.getJSONObject("data");
    JSONArray prizeLists = data.getJSONArray("prizeLists");
    
    vars.put("prizeNameValue",prizeLists.getJSONObject(1).getString("prizeName"));
    

    在DebugSampler的结果中可以看到prizeNameValue的取值是4元话费。


    总结
      本文列举出了三种可用的从 Json 格式的返回值中提取数据的方法。正则表达式对于简单的 Json 格式数据的处理非常快速标准化,JsonPath 插件可以创建能够被维护的脚本,引入fastjson库的BeanShell 依赖于 Java 语言的灵活性可以进行进一步的开发。大家可以根据自己的习惯和喜好选择任意一种进行数据的提取。



    作者:道韫
    链接:https://www.jianshu.com/p/fe5b0d70b1b3
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • Jmeter:跨线程组传递参数

    2018-01-05 09:14:34

    http://blog.csdn.net/qq_35885203/article/details/77562644

    jmeter的线程组之间是相互独立的,各个线程组互不影响,所以线程组A中输出的参数,是无法直接在线程组B中被调用的。

    但是有时为了方便管理,我们可能是把各个接口单独存放在不同的线程组中。拿token来说,虽然每一个线程组中我们也可以在放一个登录请求,然后输出一个token供此线程组使用,但这样就比较繁琐且冗余。此时我们就可以使用跨线程组传递参数来解决这样的问题


    方法:jmeter本身的内置函数中,“__setProperty”函数可以把某参数的值设置成jmeter本身的内置属性,而jmeter的内置属性是所有线程组都可以调用的,是全局变量。各个线程组调用时,只需使用调用jmeter属性的函数“__P”来调用相应的属性即可。


    操作:以Token来示例,在登录请求中添加一个正则表达式提取器(上一章有说),提取响应值中的token的值。然后再添加一个 Bean Shell PostProcessor 的后置处理器,在这个处理器中调用“__setProperty”函数,设置正则提取到的token的值为全局变量。然后在另外一个线程组中添加一个其他需要用到此token的请求,通过函数“__P”来调用token。


    流程

    1.添加Bean Shell PostProcessor后置处理器




    2. Bean Shell PostProcessor操作面板

    Parametres:把需要操作的参数传递给Bean Shell PostProcessor。前面提取出来的Token的值,就把参数Token写入

    Script:  string Token=bsh.args[0];     把Bean Shell PostProcessor接收到的参数值,赋值给某参数。0是第一个值。

                     ${__setProperty(requestToken,${Token},)};        调用函数__setProperty,把Bean Shell PostProcessor中的参数Token的值赋值给requestToken,并设置requestToken为jmeter内置属性。




    3. 其他线程组调用Token的值





  • JMeter在代理模式下,上传文件失败

    2018-01-04 09:13:50

    1.在代理模式下,如果网页有上传文件的操作会失败,原因如下:

    Some browsers (e.g. Firefox and Opera) don't include the full name of a file when uploading files. This can cause the JMeter proxy server to fail. One solution is to ensure that any files to be uploaded are in the JMeter working directory, either by copying the files there or by starting JMeter in the directory containing the files.

    解决方法:

    将上传文件拷贝到jmeter/bin目录下上传即可

  • Jmeter的参数签名测试

    2018-01-02 22:34:21

    https://www.jianshu.com/p/240e929323a6

    简介

    参数签名可以保证开发的者的信息被冒用后,信息不会被泄露和受损。原因在于接入者和提供者都会对每一次的接口访问进行签名和验证。

    签名sign的方式是目前比较常用的方式。

    • 第1步:接入者把需求访问的接口的所有必要的参数信息(注意是所有参数),除去sign本身,以及值是空的参数,按参数名字母顺序排序。拼接成字符串

    • 第2步: 然后把排序后的参数按参数1值1参数2值2…参数n值n(这里的参数和值必须是传输参数的原始值,不能是经过处理的,的方式拼接成一个字符串。

    • 第3步: 把分配给接入方的验证密钥key(或者是提供者提供的一个SECRET_KEY,这个SECRET_KEY只有接入者和提供者知道)拼接在第2步得到的字符串前面。

    • 第4步:对加入密匙key的字符串进行加密或是摘要(用MD5或是SHA1摘要的比较多)

    • 第5步:对MD5的摘要结果转成大写然后写成字符串,传给参数sign

    举例:
    假设传输的数据是
    http://www.xxx.com/interface.aspx?sign=sign_value&p2=v2&p1=v1&method=cancel&p3=&pn=vn
    (实际情况最好是通过post方式发送),
    其中sign参数对应的sign_value就是签名的值。
    
    第一步,拼接字符串,首先去除sign参数本身,然后去除值是空的参数p3,
    剩下p2=v2&p1=v1&method=cancel&pn=vn,
    然后按参数名字符升序排序,method=cancel&p1=v1&p2=v2&pn=vn.
    
    第二步,然后做参数名和值的拼接,最后得到methodcancelp1v1p2v2pnvn
    
    第三步,在上面拼接得到的字符串前加上验证密钥key,我们假设是abc,
    得到新的字符串abcmethodcancelp1v1p2v2pnvn
    
    第四步,然后将这个字符串进行md5计算,假设得到的是abcdef,
    然后转为大写,得到ABCDEF这个值即为sign签名值。
    
    注意,计算md5之前请确保接口与接入方的字符串编码一致,
    如统一使用utf-8编码或者GBK编码,如果编码方式不一致则计算出来的签名会校验失败。
    服务器用密匙key对参数进行同样的MD5摘要算法,比对sign值
    

    MD5摘要

    MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。

    MD5算法具有以下特点:
    1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。
    2、容易计算:从原数据计算出MD5值很容易。
    3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
    4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
    MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。除了MD5以外,其中比较有名的还有sha-1、RIPEMD以及Haval等

    jmeter的MD5摘要算法

    我的Jmeter3.2版本已经没有了_MD5这个函数了。
    所以要用MD5对参数进行摘要,我们需要自己导入MD5摘要算法的jar包

    用Eclipse编写一个java的MD5摘要算法的jar包

    image.png
    image.png
    image.png
    image.png

    MD5摘要算法在java中的编码
    LMFMD5.java

    package LMF.md5;
    
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    public class LMFMD5 {
        //创建一个类LMFMD5
        public String MD5(String sourceStr) {
            String result = "";
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
             // 生成一个MD5加密计算摘要
                md.update(sourceStr.getBytes());
             // 使用指定的byte数组更新摘要
                byte b[] = md.digest();
             // 把密文转换成十六进制的字符串形式
                int i;
                StringBuffer buf = new StringBuffer("");
                for (int ffset = 0; offset < b.length; offset++) {
                    i = b[offset];
                    if (i < 0)
                        i += 256;
                    if (i < 16)
                        buf.append("0");
                    buf.append(Integer.toHexString(i));
                }
                result = buf.toString();
                System.out.println("MD5(" + sourceStr + ",32) = " + result);
             //   System.out.println("MD5(" + sourceStr + ",16) = " + buf.toString().substring(8, 24));
                // 注释的是md5的16位取值
            } catch (NoSuchAlgorithmException e) {
                System.out.println(e);
            }
            return result;
        }
    }
    
    

    test.java(测试)

    package LMF.md5;
    import LMF.md5.LMFMD5;
    public class test {
        public static void main (String[] args) {
        String res = new LMFMD5().MD5("laimeifeng");
        System.out.println(res);
        }
    }
    

    把MD5摘要算法打包成jar包

    image.png
    image.png

    把MD5摘要算法的jar包放入jmeter的lib\ext目录里面里面

    image.png

    **Jmeter的BeanShell Sampler

    image.png

    Jmeter的查看MD5摘要算法结果

    image.png
    image.png
    image.png

    这样一个MD5摘要算法就成功加入到jmeter里面,可以进行MD5参数签名了。

    总结

    现在使用的接口有很大一部分是加密的,我们对这样的接口进行测试时,也需要传递加密的参数,来进行接口访问。



    作者:我为峰2014
    链接:https://www.jianshu.com/p/240e929323a6
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • Jmeter BeanShell 引用变量报错Error or number too big for integer

    2018-01-02 17:04:05

    http://www.bubuko.com/infodetail-2138759.html


    如果你通过CSV Data Set Config或者_StringFromFile函数来参数化你的请求,需要特别注意当参数为纯数字时,jmeter会默认将其识别成int型数据,说明jmeter并不是默认以String类型对数据进行读取的:范围-2147483648到2147483647,如果超出这个范围(例如2147483648这个数字):jmeter控制台则会抛出如下异常:jmeter.util.BeanShellInterpreter: Error invoking bsh method: eval    Parse error at line 14, column 181 : Error or number too big for integer type: 2147483648,如果要解决此问题,可在超出范围-2147483648到2147483647的数据前加上字母,或者使用beenshell进行参数化。

    注意:

    1、在BeenShell中引用外部参数需要以String类型的方式引用:例如:"${user}"(ps需要加上双引号)

    2、在BeenShell中引用文件路径时不要使用"\",否者会转义成ASCII码,当你需要表示完整的路径时应该如此表示:E:/TestSupplierInterFace/ZipUtil.java,而不是像java中引用E:\\TestSupplierInterFace\\ZipUtil.java,这样就会将T和Z分别转码成84和90然后jmeter控制台就会报错

  • jmeter md5 beanshell处理动态生成请求参数签名

    2018-01-02 16:34:57

    http://blog.hissummer.com/2017/01/jmeter-jsr223-beanshell%E5%A4%84%E7%90%86%E5%8A%A8%E6%80%81%E7%94%9F%E6%88%90%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0%E7%AD%BE%E5%90%8D%EF%BC%88%E4%BE%8B%E5%A6%82%E5%BE%AE%E4%BF%A1%E5%BC%80%E6%94%BEapi/

    import java.util.TreeMap;
    import java.util.Set;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Arrays;
    import java.security.MessageDigest;
    import java.math.BigInteger;
    import java.nio.charset.StandardCharsets;
    import java.nio.charset.Charset;
    import com.wjika.test.mymd5;
    import java.lang.String;
     
    //long requestTime = System.currentTimeMillis();
    String c_time="${__time(,)}";
    System.out.println(c_time);
    vars.put("current_time",c_time);
    String requestTime = c_time;
    // 原始请求参数定义
    //key1=value1&key2=&key3=value3    key2 为空将不会被作为签名的字符串并被舍弃请求。 具体请参见接口文档。
    // 此处会自动添加sign 参数,sign可以不填或者留空即可。
     
    String riginalparametersString = "app_version=5.0.1&bundleid=com.jy.gr&channel=799&current_time="+requestTime+"&imei=A10000563"+"&sign=&version=1.0&"+"mobile="+"${mobile}";
    String[] parameters = originalparametersString.split("&");
     
     
    log.info(originalparametersString);
     
    log.info(String.valueOf(parameters.length));
     
    TreeMap SortedParametersWithoutSign = new TreeMap();
     
     
    // 将参数按字母排序
     
    for(int i = 0 ; i < parameters.length ; i ++){
     
       String[] pandvalue  =  parameters[i].split("=");
       log.info(String.valueOf(pandvalue.length));
       if(pandvalue.length>1){
        
           String[] values = Arrays.copyOfRange(pandvalue, 1, pandvalue.length);
           log.info(String.valueOf(values.length));
           log.info(values[0]);
           if(!values[0].equals(""))
           SortedParametersWithoutSign.put(pandvalue[0],values[0]);
       }
       else{
           //SortedParametersWithoutSign.put(pandvalue[0],null);
       }
     
    }
     
    // 根据排序后的参数,组装参数。
     
    String requestParameters = "";
     
        Set set = SortedParametersWithoutSign.entrySet();
          Iterator iterator = set.iterator();
          int iterationcount = 0;
          while(iterator.hasNext()) {
     
              Map.Entry mentry = (Map.Entry)iterator.next();
              log.info("key: "+mentry.getKey()+"  ---- must:"+ mentry.getValue()   );
     
     //    if( mentry.getValue()[0].equals("Y") && !mentry.getKey().equals("sign") ){
     
                  if(iterationcount == 0)
     requestParameters += mentry.getValue();
     else requestParameters += mentry.getValue();
     
     iterationcount++;
     
     //    }
          }
     
     
    log.info(requestParameters);
     
    vars.put("requestParameters",requestParameters);

    String a=vars.get("requestParameters");

    StringBuilder stringBuilder = new StringBuilder(a);
    String signKey="jygdfgdfgdfgfdgddfgfdgo";
    String signRandom="bsdfsd34234234fsdfsdf82d";
    String sign = mymd5.getMd5(stringBuilder.append(signKey).toString()).concat(signRandom);
    System.out.println(sign);
    vars.put("sign", sign);


     
Open Toolbar