青,取之于蓝,而青于蓝;冰,水为之,而寒于水。木直中绳,輮以为轮,其曲中规。虽有槁暴,不复挺者,輮使之然也。故木受绳则直,金就砺则利,君子博学而日参省乎己,则知明而行无过矣。
一、Jmeter中参数取值
1、Test Plan中添加变量
Test Plan中设置好变量名,变量名可以在任意的位置引用,比如说在线程组中直接用${变量名}方式引用变量,步骤如下:
1、添加线程组
2、添加请求
3、添加结果查看树
2、User Defined Variables
注意:User Defined Variables定义的变量和Test Plan中定义的变量一样,不管这个组件在任何位置,在整个test plan中都可以引用这些变量。
1、添加线程组
2、添加请求User Defined Variables
3、添加请求
4、添加结果查看树
二、Jmeter中CSV Data Set Config
在做性能测试或者接口测试中,文件参数化最常用的工具摸过如此,咱们这次聊一聊这个工具怎么使用
作用:从文件中逐行读取数据,按指定的分隔符分割,赋给指定的变量。适合处理大量数据的情况
参数说明:
- Filename:文件路径。可以是相对路径也可以是绝对路径。可以是.txt文件也可以是.csv文件
- File encoding:文件编码,默认问ANSI,其它编码根据实际情况配置
- Variables Names(comma-delimited):变量名,表示将每一列赋值给一个变量,有多个列时同逗号分隔,后续通过${}引用
- Ignore first line:忽略首行
- Delimiter(use "\t" for tab):分隔符,默认为逗号
- Allow quoted data?:数据是否带引号,默认为false,如果数据中有引号(双引号)的话就会把数据连同引号一起赋值给变量,也就是原封不动的取值;如果为true的话就会把引号去掉,将引号中的值赋给标量。
- Recycle on EOF?:遇到文件结束符是否再次循环,默认为True,也就是继续从文件开头取值
- Stop thread on EOF?:遇到文件结束符是否结束线程,默认为False也就是不停止。注意:当【Recycle on EOF?】设置为True时,此项设置无效;当【Recycle on EOF?】设置为False,此项也设置为False,那么到达文件最后在引用变量就会变为<EOF>
- Sharing mode:共享模式。默认为all threads,还支持current thread group /current thread /edit
共享模式总结:
all treatds:csv文件中的数据是共享的,不管是线程数还是循环次数,都会触发接口请求参数来使用csv文件中不同行的变量数据
current thread group:在线程组内,线程数和循环次数都会触发接口请求参数变化
current thread:循环了数据就会变化,线程数不能决定更新csv文件中的数据,循环次数才可以;
以下简单的演示:
1、添加线程组
2、添加请求CSV Data Set Config
附件内容:
3、添加http request请求
4、添加结果查看树
三、Timer:定时器
- Constant Timer 固定定时器
- Uniform Random Timer 均匀随机定时器
- Constant Throughput Timer 固定吞吐量定时器
- Gaussian Random Timer 高斯随机定时器
- JSR223 Timer JSR223定时器
- Poisson Random Timer 泊松随机定时器
- Synchronizing Timer 同步定时器
- BeanShell Timer BeanShell脚本编写定时器
- Precise Throughput Timer 精准吞吐量定时器
1、Constant Timer 固定定时器
作用:通过ThreadDelay设定每个线程请求之前的等待时间(单位为毫秒)。
2、Uniform Random Timer 均匀随机定时器
作用:它产生的延迟时间是个随机值,而各随机值出现的概率均等。总的延迟时间等于一个随机延迟时间加上一个固定延迟时间,用户可以设置随机延迟时间和固定延迟时间。
总延迟时间=指定范围内的随机时间+固定延迟时间
3、Constant Throughput Timer 固定吞吐量定时器
作用: 按指定的吞吐量执行,以每分钟为单位。计算吞吐量依据是最后一次线程的执行时延。
Target throughput(in samples per minute):目标吞吐量。注意这里是每分钟发送的请求数,可以选择作用的线程:当前线程、当前线程组、所有线程组等,具体含义如下:
- this thread only: 设置每个线程的吞吐量。总的吞吐量=线程数*该值。
- all active threads in current thread group:吞吐量被分摊到当前线程组所有的活动线程上。每个线程将根据上次运行时间延迟。
- all active threads:吞吐量被分配到所有线程组的所有活动线程的总吞吐量。每个线程将根据上次运行时间延迟。在这种情况下,每个线程组需要一个具有相同设置的固定吞吐量定时器。(不常用)
- all active threads in current thread group (shared):同上,但是每个线程是根据组中的线程的上一次运行时间来延迟。相当于线程组组内排队。(不常用)
- all active threads (shared):同上,但每个线程是根据线程的上次运行时间来延迟。相当于让所有线程组整体排队。(不常用)
4、Gaussian Random Timer 高斯随机定时器
作用:每个线程的延迟时间是符合标准正态分布的随机时间停顿,那么使用这个定时器,总延迟 = 高斯分布值(平均0.0和标准偏差1.0)* 指定的偏差值+固定延迟偏移(Math.abs((this.random.nextGaussian() * 偏差值) + 固定延迟偏移))
5、JSR223 Timer JSR223定时器
JSR223计时器可以使用JSR223脚本语言生成延迟;
参考帮助文档:
https://jmeter.apache.org/usermanual/component_reference.html#JSR223_Timer
6、Poisson Random Timer 泊松随机定时器
这个定时器在每个线程请求之前按随机的时间停顿,总的延迟就是泊松分布值和偏移值之和。
上面表示暂停时间会分布在100到400毫秒之间:
(1)Lambda(in milliseconds):兰布达值
(2)Constant Delay Offset(in milliseconds):暂停的毫秒数减去随机延迟的毫秒数
7、Synchronizing Timer 同步定时器
作用:用来设置集合点,其作用是:阻塞线程,直到指定的线程数量到达后,再一起释放,可以瞬间产生很大的压力
(1)Number of Simulated Users to Group by:模拟用户的数量,即指定同时释放的线程数数量,若设置为0,等于设置为线程组中的线程数量;
(2)Timeout in milliseconds:超时时间,即超时多少毫秒后同时释放指定的线程数;如果设置为0,该定时器将会等待线程数达到了设置的线程数才释放,若没有达到设置的线程数会一直死等。如果大于0,那么如果超过Timeout inmilliseconds中设置的最大等待时间后还没达到设置的线程数,Timer将不再等待,释放已到达的线程。默认为0
同步定时器(Synchronizing Timer)的超时时间设置要求:超时时间 > 请求集合数量 * 1000 / (线程数 / 线程加载时间)
8、BeanShell Timer BeanShell脚本编写定时器
参数说明:
- Reset Interpreter:每次迭代是否重置解析器,默认为false;在长时间运行的脚本中建议设置为true。
- Parameters:BeanShell脚本的入参。入参可以是单个变量;也可以是数组,若是字符串数组,两个元素之间用空格隔开;也可以是常量。
- File Name:BeanShell脚本可以从脚本文件中读取。
- Script:在Script区直接写BeanShell脚本。
简单写一demo增加一个sleep等待一分钟:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
增加一个Java Request请求,并且增加时间验证是否按照自己设定的定时运行脚本:
Java Request ${__time(yyyy-MM-dd HH:mm:ss:SSS,)}
增加结果查看树:
结果显示按之前设置的每个1秒钟运行
9、Precise Throughput Timer 精准吞吐量定时器
- Target Throught:目标吞吐量
- Throught Period:表示在多长时间内发送Target Throught指定的请求数(以秒为单位)
- Test Druation:指定测试运行时间(以秒为单位)
- Number of threads in the bath:用来设置集合点,等到指定个数的请求后并发执行其它参数默认即可。
三、Jmeter处理器
1、前置处理器Pre Processors
用于对于采集器进行处理,且是在sampler启动之前
JSR223 PreProcessor
参数配置:
- Name:名称,随意设定;
- Language:使用的JSR223语言,可根据需要选择;
- Parameters:传递给脚本的参数;
- Script file:脚本文件;
- Script compilation caching:存储编译的脚本,默认勾选;
- Script:要运行的脚本;
User Parameters
用户参数,用于做几组参数给线程组的各个线程使用,如果线程数多于用户参数组数,则多出来的线程则从第一组用户参数开始依次调用参数组;
参数配置:
Name:此前置处理器的名称;
Update Once Per Iteration:标识是否每轮迭代更新一次元素;
HTML Link Parser
此处理器为HTML链接解析器,用于从前一个sampler返回的html页面中按照规则解析链接和表单,再根据此处理器所在的sampler中的规则进行匹配修改,而后该sampler会执行;
HTTP URL Re-writing Modifier
HTTP URL重写修改器,此处理器与HTTP Link Parser类似,但专用于使用url重写来存储sessionId而非cookie的http request,在线程组级别添加此修改器则应用于所有sample,若为单个sample添加则只适用该sample;
参数配置:
Session Argument Name:会话参数名称,用于搜索sessionId,其他sample也可通过此参数来 调用其获取的sessionId;
Path Extension:路径扩展,如url添加了分号作为分割,则勾选此项;
Do not use equals in path extension:用于url不用等号来分割key和value的类型;
Do not use questionmark in path extension:用于不带?的类型;
Cache Session Id?:勾选此项则会存储在其挂载的sample上获取到的sessionId供后边的其他sample使用;
URL Encode:是否使用url编码;
JDBC PreProcessor
数据库预处理器,用于在sample开始前查询数据库并获取一些值;
参数配置:
Variable Name of Pool declared in JDBC Connection Configuration:连接池名称,需与JDBC链接配置中的Variable Name相同(此预处理器需要一个JDBC Connection Configuration,此配置器在配置元件中);
Query Type:数据库查询类型,根据需要自行选择;
Query:数据库语句输入框,根据需要输入,注意结尾不要加”;”;
Parameter values:参数名称,如果Query的语句中有”?”则此处填值,可以使用调用参数方式;
Parameter types:参数类型,与Parameter values对应,设置参数类型,与sql字段类型相同;
Variable names:设定此项可以获取固定列的所有值;
Result variable name:随意设定一个名称,则此名称会被作为一个参数并对应Query出来的内容;可以使用参数调用的方法来获取此设置的名称对应的值;
Query timeout(s):超时时间;
Handle ResultSet:有四个选项,结果保存的方式;
RegEx User Parameters
正则表达式,使用正则表达式为从另一个HTTP请求中提取的HTTP参数指定动态值
参数配置:
name:此前置处理器名称;
Regular Expression Reference Name:调用的正则表达式提取器中的引用名称;
Parameter names regexp group number:用于提取参数名称的正则表达式的组编号;
Parameter values regex group number:用于提取参数值的正则表达式的组编号;
Sample Timeout
超时器,用于设定sample的超时时间,如果完成时间过长,此预处理器会调度计时器任务以中断样本;
参数配置:
name:超时器名称;
Sample timeout:超时时间;
BeanShell PreProcessor
参数配置:
Name:名称,随意设定;
Language:使用的JSR223语言,可根据需要选择;
Parameters:传递给脚本的参数;
Script file:脚本文件;
Script compilation caching:存储编译的脚本,默认勾选;
Script:要运行的脚本;
四、综合脚本小练习
一、在造数据时候,需要获取结果到保存到本地
有两种方式:第一种直接通过获取结果保存到本地,第二种通过数据库导出
今天介绍第一种,通过jmeter中正则表达式获取:
步骤一:
第二步:
第三步
参考代码
FileOutputStream fps=new FileOutputStream("${outfile_online}",true);
OutputStreamWriter osw=new OutputStreamWriter(fps);
BufferedWriter bw=new BufferedWriter(osw);
bw.append("${mobile}\t${User}\t${User}\t${fd}\n");
if(bw!=null){bw.close();}
if(osw!=null){osw.close();}
if(fps!=null){fps.close();}
第四步
获取结果
2、后置处理
从上面可以看出后置处理可以插件挺多,在我工作生涯中常用的就是几个组件,
1、Regular Expression Extractor(正则表达式提取器)
Apply to:应用范围
- Main sample and sub-samples:作用于主节点的取样器及对应子节点的取样器
- Main sample only:仅作用于主节点的取样器
- Sub-samples only:仅作用于子节点的取样器
- JMeter Variable:作用于jmeter变量(输入框内可输入jmeter的变量名称),从指定变量值中提取需要的值。
Field to check 要检查的响应字段:
1、Body 主体:响应报文的主体,最常用
2、Body(unescaped):主体,是替换了所有的html转义符的响应主体内容,注意html转义符处理时不考虑上下文,因此可能有不正确的转换,不太建议使用
3、Body as a Document:从不同类型的文件中提取文本,注意这个选项比较影响性能
4、Response Headers:响应信息头(如果你使用的是中文版的Jmeter,会看到这一项是信息头,这是中文翻译问题,应以英文为准)
5、Request Headers:请求信息头
6、URL:请求url
7、Response Code:响应状态码,比如200、404等
8、Response Message:响应信息
Name of created variable 引用名称:其他地方引用时的变量名称,我这里写的phone,可自定义设置,引用方法:${引用名称}
Regular Expression 正则表达式:数据提取器,()括号里为你要获取的的值。"mobilephone":"( 相当于LR左边界, )","leaveamount"相当于LR右边界。而括号里\d+为正则表达式,用来匹配所需要获取的数据,何谓正则表达式文章末尾会附上说明
Template 模板:用于从找到的匹配项创建字符串的模板。这是一个带有特殊元素的任意字符串,用于引用正则表达式中的组。引用组的语法是:' $ 1 $ '引用组1,' $ 2 $ '引用组2,等等。$ 0 $引用整个表达式匹配的内容。
Match No. 匹配数字:正则表达式匹配数据的所有结果可以看做一个数组,匹配数字即可看做是数组的第几个元素。-1表示全部,0随机,1第一个,2第二个,以此类推。若只要获取到匹配的第一个值,则填写1
Default value 缺省值:匹配失败时的默认值。可以不写。若需用于后续逻辑判断,可简单写为 ERROR。
简单示例:
1、添加线程组
2、添加请求
3、添加正则提取器
首先请求一次,在结果查看树中调试正则表达式,增加正则提取器,把正则表达式放上去
增加正则表达式
增加调试器
4、添加结果查看树
2、JSON Extractor(JSON表达式提取器)
3、Regular Expression Extractor(正则表达式提取器)
说明:
1.Variable name :自定义参数名,引用的时候${} 格式
2.Json path expression:json表达式,根据上面的json,表达式为:$.开始
简单样例说明:
1、添加线程组
2、添加请求
1、使用springboot新建工具简单写好Controller代码如:
@GetMapping("/weixin")
@ResponseBody
public Msg getWeixint() {
HashMap<String, ArrayList<Skills>> hashMap1 = new HashMap<>();
HashMap<String, ArrayList<Gender>> hashMap = new HashMap<>();
HashMap<String, String> hashMap3 = new HashMap<>();
hashMap3.put("name", "数据下发");
hashMap3.put("opinion", "get获取得数据");
ArrayList<Gender> list = new ArrayList<>();
list.add(new Gender("男", "0", true));
list.add(new Gender("女", "1", true));
ArrayList<Skills> list1 = new ArrayList<>();
list1.add(new Skills("HTML", "html", true));
list1.add(new Skills("CSS", "css", false));
list1.add(new Skills("JavaScript", "js", false));
list1.add(new Skills("Photoshop", "ps", true));
list1.add(new Skills("python", "py", true));
hashMap.put("gender", list);
hashMap1.put("skills", list1);
HashMap<String, Object> hashMap2 = new HashMap<>();
hashMap2.putAll(hashMap);
hashMap2.putAll(hashMap1);
hashMap2.putAll(hashMap3);
System.out.println(hashMap2);
return Msg.success().add("infopage", hashMap2);
}
启动成功如:
页面响应如:
添加请求
3、添加结果查看树调试
4、添加JSON Extractor
5、添加Debug Sampler
6、查看结果
3、工程结构如下:
很多插件需要在工作不断练习才能掌握,掌握学习方法,并且自己动手就能把很多事情做出来;
观书有感
【作者】朱熹 【朝代】南宋
半亩方塘一鉴开,天光云影共徘徊。
问渠那得清如许?为有源头活水来。