关于Jmeter参数化的编码问题

大家用jmeter最常遇到的是请求参数中文乱码问题(至于返回值乱码问题由于处理简单也不影响测试,就不在这里说了),而对于这个问题,很多人不能从根本上去分析和理解,所以就无法从根本上去回避和解决,以下我就通过几种情况来分别说明:

在这之前,先做好测试案例:

(1)准备CSV数据文件,内容只有三列:1,test,测试

关于Jmeter参数化的编码问题_第1张图片

注意:这里的文件名含路径,linux下必须是csvData/ID2.csv(如果用反斜杠,在linux下就找不到文件,而jmeter4.0非常糟糕的一点是正斜杠保存完后也会变成反斜杠,只能通过编辑器批量修改,为了避免麻烦,可以不用像我这样,只要把脚本和csv保存在bin下就行,这样只需要输入文件名ID2.csv即可)。

(2)分别准备三个请求,这三类请求基本覆盖了常见的参数化乱码问题

一个是在请求名称中带所有参数,用的是BeanShell

关于Jmeter参数化的编码问题_第2张图片

一个是key-value参数格式的请求

关于Jmeter参数化的编码问题_第3张图片

一个是Body Data格式的请求

关于Jmeter参数化的编码问题_第4张图片

下面我们就可以开始测试了。

场景一:默认ANSI/ASCII格式的参数化文件

我们在设置CSV数据文件时,文件编码置空不做选择,进行测试后发现在windows下两请求编码正常(第3个请求后面再说):

关于Jmeter参数化的编码问题_第5张图片

而在Linux下却是乱码

关于Jmeter参数化的编码问题_第6张图片

我们做一下设置,在设置CSV数据文件时,加上GBK编码

关于Jmeter参数化的编码问题_第7张图片

这时再测试,就会发现linux下和windows下都正常编码了。

关于Jmeter参数化的编码问题_第8张图片

关于Jmeter参数化的编码问题_第9张图片

注释:设置CSV数据文件,编码项是可选的,但不一定会有GBK选项,要么手填,要么修改jmeter.properties

关于Jmeter参数化的编码问题_第10张图片

场景二:用UTF-8格式的参数化文件(最好是用编辑器保存为UTF-8 无bom头)

同样默认情况下设置CSV数据文件时,文件编码置空不做选择

关于Jmeter参数化的编码问题_第11张图片

我们将UTF-8格式的ID2.csv同时覆盖到windows和linux下进行测试

我们发现windows下显示乱码了

关于Jmeter参数化的编码问题_第12张图片

而linux下却正常了

关于Jmeter参数化的编码问题_第13张图片

同样我们做一下设置,在设置CSV数据文件时,加上UTF-8编码

关于Jmeter参数化的编码问题_第14张图片

保存后再进行测试,发现windows下和linux下都正常了

关于Jmeter参数化的编码问题_第15张图片

关于Jmeter参数化的编码问题_第16张图片

通过以上两个场景的对比测试,我们发现一个道理,就是设置CSV数据文件时,文件编码的配置是在告诉jmeter,将以什么编码格式显示参数文件的数据,如果不配置即按操作系统的默认编码格式显示(windows下是GBK或gb2312,linux下是UTF-8)。而一旦出现显示的编码格式与csv文件的编码格式不统一时,就会出现乱码。为了避免错乱,我们就统一将CSV保存为UTF-8格式,统一在设置CSV数据文件的面板中,文件编码选择UTF-8。

场景三:对Body Data格式请求的中文参数测试

在确保以上两个场景的问题处理完后,我们是否就解决了乱码问题,答案是否定的。因为以上的方式只是保证jmter发送的URL请求格式不会有乱码,但不能保证body或json中是否没有乱码。在前两个请求都正常的情况下,我们在看看第三个请求的结果:

关于Jmeter参数化的编码问题_第17张图片

为什么会这样,我们通过解开jmeter的源代码,就能找到答案(以下是节选PostWriter.java中的两段源码):

 

 

public static final String ENCODING = StandardCharsets.ISO_8859_1.name();

    public String sendPostData(URLConnection connection, HTTPSamplerBase sampler) throws  IOException {
        // Buffer to hold the post body, except file content
        StringBuilder postedBody = new StringBuilder(1000);
        HTTPFileArg[] files = sampler.getHTTPFiles();

        String contentEncoding = sampler.getContentEncoding();
        if(contentEncoding == null || contentEncoding.length() == 0) {
            contentEncoding = ENCODING;
        }

        //此处省略代码.......
        return postedBody.toString();
    }

通过以上代码可以看出,PostData是需要设置编码格式的,而且默认编码字符是ISO_8859_1(第一行代码),编码读取的是Content Encoding,这个在jmeter的http请求面板上就能看到。我们配置成UTF-8试试:

关于Jmeter参数化的编码问题_第18张图片

发现还是乱码,但是这个乱码能看出已经能够识别出utf-8字符了:

关于Jmeter参数化的编码问题_第19张图片

这也说明了编码还是不一致,死记万能的UTF-8是行不通的,我们换个GBK或gb2312试试:

关于Jmeter参数化的编码问题_第20张图片

正常显示中文了!!!!!

场景四:还有种编码叫URLEncoder

不是所有的请求,直接发送中文就能正常得到响应,这还要取决于web应用服务端的相关编码处理。先了解一下什么是URLEncoder:url编码是一种浏览器用来打包表单输入的格式。浏览器从表单中获取所有的name和其中的值 ,将它们以name/value参数编码(移去那些不能传送的字符,将数据排行等等)作为URL的一部分或者分离地发给服务器。

为了避免明文发送中文或是去除/转译非法字符,URL编码是非常必要的,在http请求中对URL参数进行URL编码的方式如下(勾选编码):

关于Jmeter参数化的编码问题_第21张图片

进行URL编码后的请求效果如下:

关于Jmeter参数化的编码问题_第22张图片

当然也可以通过BeanShell PreProcessor来实现对{name}参数URL编码,如下:

vars.put("name",URLEncoder.encode("${name}","UTF-8"));

有了编码,就有解码URLDecoder.decode,这是在应用服务端实现的。我们也可以在jmeter上模拟解码过程,如下:

vars.put("name",URLDecoder.decode("${name}","utf-8"));

针对中文参数化的编码问题,我们就举这四个场景,当然解决的方式不仅限于上面所罗列的。思路是一样的,方法是多样的,包括直接修改jmeter的源码,重新编译一个你自己的jmeter也行。通过以上的方式,我们也发现utf-8编码是相对通用的,因为在linux下和windows下都能得到相应的解决和处理。

附:其他注意事项

1、默认linux可能不支持中文,可以通过以下方式简单处理:

编辑i18n配置文件: vi /etc/sysconfig/i18n

进行如下配置并保存退出:

#LANG="en_US.UTF-8"
LANG="zh_CN.UTF-8"
SYSFONT="latarcyrheb-sun16"

执行以下命令即时生效
source /etc/sysconfig/i18n

2、在linux下对于jmeter的csv参数文件不要命名为ID.CSV

原因不明,至少在jmeter4.0下测试发现了问题,这样命名的文件,要么是发送消息为乱码,要么是读取不到参数。

3、将csv参数统一为UTF-8编码是解决编码兼容性的好办法,以下提供一个我自己写的在linux下批量转换csv为utf-8编码的脚本:

#!/bin/bash
### 将 values_here 替换为输入编码
#FROM_ENCODING="value_here"
### 输出编码 (UTF-8)
TO_ENCODING="UTF-8"
### 转换命令
#CONVERT=" iconv -f $FROM_ENCODING -t $TO_ENCODING"
### 使用循环转换多个文件
for file in *.csv; do
  rm -f ${file%.csv}.csv.bak #先清理备份文件
  mv ${file%.csv}.csv ${file%.csv}.csv.bak #转换前先备份文件
  #以下为获取csv文件的原编码格式
  FROM_ENCODING=$(file -i ${file%.csv}.csv.bak | awk '{print $3}' | sed '1s/charset=//g')
  #对于识别不了的编码暂时归为GBK
  if [ "$FROM_ENCODING" = "unknown-8bit" ];then
    FROM_ENCODING=$(echo "GBK")
  fi
  CONVERT=" iconv -f $FROM_ENCODING -t $TO_ENCODING"
  $CONVERT "${file%.csv}.csv.bak" -o "$file"
  #$CONVERT "$file" -o "${file%.csv}.csv"
done
exit 0

将脚本放在csv文件目录下,给脚本赋可执行权限,执行完后就能将当前目录下的csv编码格式全转成utf-8

你可能感兴趣的:(软件测试,#,性能测试,#,Jmeter,#,接口测试,Jmeter自动化测试,jmeter,乱码,编码,CSV参数,URLEncoder)