Jmeter入门

简单发送get post请求

Jmeter各个元件的作用域和执行顺序

取样器只对自己其作用(大概就是这个意思)
逻辑控制器只对子节点里的逻辑控制器和取样器起作用
其他元件如果父节点不是取样器,对于所有姐妹节点起作用。如果父节点是取样器,那么只对父节点起作用

执行顺序:
配置元件 -> 前置处理器 -> 定时器->取样器 ->后置处理器 ->断言->监听器

Jmeter线程组属性

线程数:模拟的虚拟用户数,线程数为n,则线程组下的所有取样器请求会被发起n次
Ramp-up time(second): 顾名思义,几秒内模拟完所有虚拟用户,即发起线程组下的所有取样器请求
循环次数:
永远代表一直不停地执行测试计划,永远可以和调度器一起结合使用,如果调度器的启动延迟设为5秒,持续时间设为20秒,这就代表会延迟5s启动线程组下所有取样器请求,5s后开始发起请求,并且运行时间维持20s

在这里插入图片描述
除永远外,可以自定义循环次数,循环次数意味着线程组里取样器请求会被发起多少次

mock模拟路径带参数的get接口

java -jar ./moco-runner-1.1.0-standalone.jar http -p 18003 -c conf1.json
conf1.json 👇

[
  {
    "description":"这是我们的第一个mock例子",
    "request":{
      "uri":"/demo",
      "method": "get",
      "queries": {
        "name": "cxy",
        "age": "30"
      }
    },
    "response":
    {
      "text":"Hello,Moco"
    }
  }
 ]
 

模拟接口http://ip:port/demo?name=“xxx”&age=“xxx”

Jmeter请求get接口

在这里插入图片描述

mock模拟带form-data格式的post接口

{
    "description": "这是一个带form-data格式参数的post",
    "request": {
      "uri": "/postWithForm",
      "method": "post",
      "forms": {
        "name": "cxy",
        "age": "30"
      }
    },
    "response": {
      "json": {
        "isSuccess": "true"
      }
    }
  }

Jmeter请求带form-data格式参数的post接口

在这里插入图片描述

mock模拟带json格式参数的post请求

  {
    "description": "这是一个带参数的post请求",
    "request": {
      "uri": "/postWithParam",
      "method": "post",
      "json": {
        "name": "cxy",
        "age": "18"
      }
    },
    "response": {
      "status": 200,
      "json": {
        "name": "cxy",
        "age": 18
      }
    }
  }

Jmeter请求json格式参数的post接口

在这里插入图片描述

Jmeter实现全局(针对线程组)常量可灵活配置

服务端的ip port这些参数是通用的,如果改变了那么所有接口都需要改,可以通过参数化实现只要改变一处,不用所有接口的ip port都要改
添加配置元件->用户定义的变量
在这里插入图片描述
在这里插入图片描述

如何查看请求响应

添加监听器->查看结果树
运行后结果树里可以查看请求头请求体响应头响应体

如何解决响应里中文乱码

将bin目录下的jmeter.properties的encoding编码格式从默认的ISO改成utf-8格式
chensiyue@magicBook bin % pwd
/Users/chensiyue/Downloads/apache-jmeter-5.5/bin
chensiyue@magicBook bin % vim jmeter.properties

# The encoding to be used if none is provided (default ISO-8859-1)
sampleresult.default.encoding=utf-8

逻辑控制器

通常逻辑控制器和取样器会构成父子关系,从而实现逻辑控制关系。如下图所示
在这里插入图片描述

逻辑表达式

逻辑控制器最关键的是一个逻辑表达式expression,根据逻辑表达式的true或者false判断是否执行逻辑控制器下的子节点
最简单的可以直接写true or false
在这里插入图片描述
也可以间接引用一个true or false的变量
在这里插入图片描述
更复杂的表达式,比如有> < >= ! && || 这些逻辑控制符,需要按照以下格式写

${__jexl3(逻辑表达式,像平时java语言一样写)}

ps 逻辑表达式中如果有引用变量,用${}去引用
举个🌰

> ${__jexl3( ${condition}==3&&${ifrun} )}

Jmeter连接Mysql数据库并执行sql

引入jdbc jar

因为需要使用jdbc request取样器,通过jdbc连接mysql数据库,所以需要添加第三方jar包(和springboot里maven引dependency一个道理),在测试计划中添加jar包
添加/Users/xxxx/Learning/maven_repo/com/mysql/mysql-connector-j/8.0.33/mysql-connector-j-8.0.33.jar
在这里插入图片描述

添加JDBC connection configuration

配置元件->JDBC connection configuration
在这里插入图片描述
其中有一些数据库连接池属性,比如数据库连接池中最大连接数 获取连接最长等待时间
这些都和springboot继承Druid连接池属性很像,可以参考

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=19991216csy

# 初始化大小,最小,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000

添加JDBC request

数据库连接池名写JDBC连接配置元件里配置的数据库连接池名
没有参数的sql查询语句选择Select Statement
在这里插入图片描述

查看sql查询结果

和Http 请求一样,用监听器->查看结果数就可查看sql查询结果了
在这里插入图片描述

SQL查询条件参数化

在这里插入图片描述

场景:查询user表中年龄大于22的数据
在配置元件->用户定义的变量中定义一个变量minAge=22
第一种写法:sql语句里直接引入变量
在这里插入图片描述
第二种:在查询语句中用?作为占位符,在下面的参数中引入变量
在这里插入图片描述

SQL查询结果参数化

在这里插入图片描述
查询结果会被保存为变量名id,name
但查询记录不会只有一条,所以如果想引用变量的话,可以以

${id_索引} ${name_索引}

的形式去引用变量,比如${id_1}
如果想查看变量是否被保存,添加取样器->调试取样器
在这里插入图片描述

参数化

CSV文件参数化

首先将所有参数值写入一个后缀名为.csv的文件
举个🌰
test_data.csv

userName,password
csy,1234
gtz,12345
zz,3456
cms,58320
接着在线程组中添加配置元件->CSV Data set config

在这里插入图片描述
CSV Data Set Config各个属性的含义:
文件名:csv文件所在路径(csv文件可以直接由excel文件改后缀名)
文件编码:一般设置成UTF-8即可
变量名称:给csv文件里读出来的参数值起名字,如果csv文件里首行是变量名的话,可以和csv文件中的变量名不同,各个变量名用,隔开
忽略首行:True,代表忽略了首行,当csv文件首行是变量名而不是参数值的时候,需要设为True忽略首行;False代表不忽略首行,直接从首行开始读参数值;
分隔符:每行各个参数值之间用什么符号隔开,一般都是“,”当然也可以用制表符
是否允许带引号:
有些博客上写的是如果设置为true,那么csv文件中如果有参数值为"noora",那么参数值实际取为noora;如果为false,那么参数值仍旧是"noora";
但是实际实验了一下发现无论是设为true/false,取出来的值都是noora;挺奇怪的

在这里插入图片描述
遇到文件结束符再次循环(recycle on EOF):true,代表如果jmeter如果读到文件结束符(文件结束符在java中是-1,即文件全部读完),且线程组还未结束,那么就会从文件开头重新开始读参数值;false代表如果读到文件结束符,那么即使线程组还未结束,也不会再从文件头开始重新读,而是直接将EOF文件结束符作为参数值读出给变量提供给线程组引用;
比如:设为true的话,csv 文件共有 10 条记录,但线程数有 15 个,循环 10 次后,重头开始循环取值。
设置为false后,参数文件不再循环遍历取值。
如下
recycle on EOF=false,线程组线程数为6,但只有4组参数值,那么剩下的两组参数值只能为EOF
在这里插入图片描述
遇到文件结束符停止线程stop thread on EOF:为true的话,代表如果读到文件结束符,即便线程组还未执行完所有线程,那么线程组也直接强行结束;
举个🌰
csv文件有五组数据

userName,password
csy,1234
gtz,12345
zz,3456
cms,58320
“noora”,“97”

线程组线程数设为6
在这里插入图片描述

那么也只会执行五个线程
在这里插入图片描述
如果stop thread on EOF设为false的话,那么即使文件已经读到末尾,也会继续执行完所有线程组,要么从头开始读文件中参数要么直接拿EOF作参数值;

线程共享模式(Sharing mode)(这部分存疑)
所有线程(All threads): 参数文件对所有线程共享,这包括同一测试计划中的不同线程组(测试计划下的所有线程组下的所有线程共享参数文件,所有线程之前参数取值互相影响,线程在同一次迭代下取值相同)(但实际上测下来好像不是这样??,同一个测试计划下的线程组并不共享变量)
当前线程组(Current thread group): 只对当前线程组中的线程共享(当前线程组下的所有线程公用一个参数文件,同一个线程组下的线程之前取值相互影响,线程在同一次迭代下取值相同)
当前线程(Current thread): 仅当前线程获取(即每个线程获取一个参数文件,各个线程之间参数取值互不影响,线程在同一次迭代下取值相同)

函数生成参数

定义好参数值,直接拷贝函数字符串作为变量即可
在这里插入图片描述

用户定义的变量

配置元件->用户定义的变量
所有用户取到的变量都是统一的,适用于一些全局的静态变量定义

用户参数

前置处理器->用户参数
在这里插入图片描述
和用户定义的变量不同的是,每个用户都可以取到不一样的参数值,举个🌰,如上图定义了两个变量,每个变量各两个参数值。
定义线程组共三个线程,那么线程1取用户1的值,线程2取用户2的值,线程3循环取用户1的值
在这里插入图片描述

关联 断言 聚合报告

部署一个电商项目

在进行接口测试之前,首先在本地部署一个电商项目用于之后的接口测试,就不用mock模拟接口了。
用的电商项目也是有点烂大街的。
源码连接
慕慕生鲜https://github.com/csushl/imooc_mall
git clone下来之后maven package一下打个jar包,或者直接下载网盘链接

链接: https://pan.baidu.com/s/1nBILNbsgnOTg9JLYG6jwWg?pwd=1111 提取码: 1111 复制这段内容后打开百度网盘手机App,操作更方便哦

下载下来之后解压一下,建一个数据库,这个电商项目有用redis缓存,redis安装,改一下配置文件里的数据库和redis配置信息,之后用nohup java -jar xxx.jar &后台运行这个项目,如果想结束运行,ps -ef|grep xxx.jar再kill进程就可以。
部署好之后,可以http://ip:port/swagger-ui.html访问swagger注解自动生成的接口文档。

关联

关联接口场景

会有这样一种场景,接口A的响应参数是接口B的请求参数,也就是两个接口是关联的。对于这种关联接口,需要给接口A添加响应提取器,响应提取器分为三类,JSON提取器(只要是Json格式的响应,都可以用这个提取)、正则表达式提取器(任何格式的响应都可以用正则表达式提取)、Xpath提取器(xml格式或者html格式的响应可以用Xpath提取)

举个🌰
登陆接口
在这里插入图片描述
登陆接口会返回token
商品添加购物车接口
在这里插入图片描述
在源码中有添加自定义过滤器filter,对指定的url会进行过滤
过滤器的原理(spring mvc的原理最好也要知道一下)
在这里插入图片描述

/cart/路径下的所有接口都要经过过滤器的doFilter方法
在这里插入图片描述
自定义filter的doFilter方法
如果请求头没有添加token的话,请求失败。/cart/下的接口需要在请求头中添加jwt_token
在这里插入图片描述
总的来说就是提取登陆接口响应中的data值作为商品添加购物车接口的请求头中的jwt_token值
登陆接口响应

{"status":10000,"msg":"SUCCESS","data":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX3JvbGUiOjIsInVzZXJfaWQiOjksInVzZXJfbmFtZSI6Imltb29jIiwiZXhwIjoxNzczNjUyNTIyfQ.oA2gp0a3Gl-c2_HzMRAuBI8j5mjC2TvM3G_2ooWvJ0s"}

Json提取器

对于JSON格式的响应,可以用json提取器来提取。
JSONPath ref:
JSONPath vs Xpath
提取Json Path:
在这里插入图片描述
JSON提取器的各属性详细描述:
在这里插入图片描述

将提取出来的jwtToken变量作为商品添加购物车接口的请求头:
在接口请求下添加Http信息头管理器构成父子关系,就只会对父节点起作用;如果请求头直接放在和取样器同级下面,就对所有接口起作用了
在这里插入图片描述

正则表达式提取器

data的正则表达式:

{.*"data":"(.*)"}

注意要提取出来的参数一定要用()括起来,提取器会取括号里的group作变量。
这个有点类似正则API 中的Matcher.group()
在这里插入图片描述
ps.👇这个网站作正则匹配很好用
https://regex101.com

在这里插入图片描述
正则表达式提取器的各属性详细描述:

在这里插入图片描述

Xpath提取器

Xpath提取是针对xml. html格式的响应进行提取的。
Xpath语法可以对比JsonPath一起看。
1、层级,/代表子节点 //代表递归所有子节点也可以理解为跳级(对应jsonPath . …)

2、属性 @href就表a标签里的href

3、函数 常用的是contains(@属性名,”xxx”)

4、表达式 在标签名后加[] []里可以写表达式 如h1[expression](对应JsonPath [(expression)]

断言

断言主要分成三种,JSON断言(适用于所有JSON格式的响应),响应断言(任意格式的断言),持续时间断言(适用于需要用响应时间作为评判标准的接口)
如果断言失败的话,那么即使接口响应成功,查看结果树里接口下的子节点JSON断言也是assert false.
如下图
在这里插入图片描述

JSON断言

所有JSON格式的响应都可以用JSON断言。
举个🌰
判断登陆接口响应的if msg==SUCCESS
在这里插入图片描述
JSON断言各个字段的含义:
在这里插入图片描述

响应断言

响应断言适用于任何格式的响应。
举个🌰
判断商品加入购物车接口if msg==SUCCESS
用的是正则表达式匹配
在这里插入图片描述
响应字段各字段含义:
1、Apply to
断言的作用域,一般默认Main Sample only断言的作用域只是断言的父节点取样器。
没有对其他作用域做研究。下次要用时可以查一下
2、测试字段
指的是对请求对哪一个字段做断言。
响应文本指的是response body
响应代码指的是200 302 400 401 403 404 500这些(200成功,302请求重定向 400客户端请求参数有问题 401unathorized 客户端携带里错误的未被授权的身份鉴权信息。403 forbidden服务端拒绝客户端访问 404url找不到 500服务端问题)
在这里插入图片描述
响应信息:
响应信息指的是OK,Bad request这种。如下图
在这里插入图片描述

响应头请求头…
其他的要用的时候再看。
ref:这个写的很详细
https://blog.csdn.net/weixin_37600187/article/details/129063573

模式匹配规则

包括:测试字段包括指定的字符串,可以用正则表达式
匹配:测试字段和制定的字符串完全匹配或者一致,可以使用正则表达式
相等:测试字段和指定的字符串完全相等,不支持正则
字符串:测试字段包含指定的字符串,不支持正则
否:将断言的结果反过来(大概这个意思)
或者:和其他模式匹配是或的关系,只要一个模式成功则断言成功。
举个🌰
在这里插入图片描述
1在这里插入图片描述

持续时间断言

判断响应时间是否超过X ms,如果超过x ms那么断言失败
在这里插入图片描述

聚合报告

聚合报告最关键的是里面各个参数的含义要搞清楚
在这里插入图片描述

样本:每个请求发起的数量,如果线程数即虚拟用户数为10,循环次数为10,那么请求次数为10*10=100
平均值:每个请求平均响应时间(ms)
中位数:50%用户响应时间小于该值
90%百分比:90%用户响应时间小于该值
95%百分比99%百分比:以此类推
最小值:最小的响应是时间
最大值:最大的响应时间
异常%:错误率=错误请求的数量/请求的总数。
吞吐量:每秒完成的请求数
Received KB/sec (接收数据):每秒从服务器端接收到的数据量
Sent KB/sec(发送):每秒发送到服务器端的数据量

慕慕生鲜电商项目性能测试

网上有一个已经部署到服务器上的网站
http://8.134.147.252:8081/#/index
对电商项目做性能测试做性能测试,先搞清楚大致流程
消费者注册
由于注册接口需要邮箱中的验证码,所以可以直接向数据库注册用户表里添加用户数据记录。
在这里插入图片描述
但是数据库中的密码是MD5加密过的字符串,所以插入用户数据记录的时候也需要将密码加密,相当于要模拟java代码中的注册逻辑。
可以利用取样器->BeanShell取样器, Beanshell中的脚本可以采用java语法,如下分别是随机生成用户名和对密码加密的脚本

import org.apache.commons.lang3.RandomStringUtils;

String username = RandomStringUtils.randomAlphabetic(10);
vars.put("userName","test"+username)


import java.security.MessageDigest;
import org.apache.commons.codec.binary.Base64;

String strValue="12345678";
MessageDigest md5 = MessageDigest.getInstance("MD5");
String password = Base64.encodeBase64String(md5.digest((strValue + "8svbsvjkweDF,.03[").getBytes()));
//vars是jmeter内置的一个线程组局部map
vars.put("password",password)

下面的接口都平平无奇,只要掌握之前的基础知识完全可以很容易地写出来

消费者登陆

消费者商品加入购物车

消费者查看购物车

消费者创建订单

消费者查看订单详情

消费者支付

商家登陆

商家发货

确认收货

设置并发数即线程数,添加聚合报告

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值