一、复习:
设置JMeter默认打开语言风格:
修改jmeter.properties文件 属性文件、配置文件 名值对
供JMeter在启动时,作为初始化配置使用
#language=en 默认英文版en 改为简体中文zh_CN
language=zh_CN
重启jmeter
1、接口测试的前提:
1)需求文档(功能需求、性能需求) 客户、需求分析师
是后续设计、开发、测试、实施的依据
2)接口文档(API文档、开发文档)
由开发方的系统设计人员编写的,作为后续开发的重要依据,也作为测试的依据;
如果没有接口文档? 分析协议 HTTP 简单的、无状态的
如果有UI界面,可以使用Fiddler就行抓包,获取核心功能、动作的数据报文(请求包、应答包),从请求的头部header获得URL、请求方式get/post、URL后携带的参数(Query String 查询字符串 ?参数名=参数值&...)、支持的编码类型 Accept-Encoding: gzip, deflate、内容类型Content-Type、是否携带Cookie信息(客户端保存用户状态信息的技术); 从请求的主体body获取post方式携带的参数(参数名=参数值&... 或者是JSON文本提交给服务器);
从响应中获取服务器接口的返回信息:从响应头部header获取HTTP响应码(2xx 3xx 4xx 5xx)、响应内容类型Content-Type、是否让客户端保存Cookie(Set-Cookie: 名=值;xxx=xxx); 从响应的主体body获取响应文本内容,比如JSON、XML、HTML、JS、CSS、JPG、mp4等;接口测试时,可以将返回的JSON结果进行改写,作为新业务的检查依据(数据格式一样,数据内容不同);
作为接口测试,主要是对某些核心功能发送请求,一般结果以JSON或XML格式为主,表示返回重要结果数据,作为前端、下一步显示、判断的重要依据;
如果既没有接口文档、界面也未实现,如何测试接口?需要和开发方获取重要的协议信息,尤其是接口文档;
二、JMeter核心技术
1、什么是JMeter?
JMeter是由Apache基金会组织提供的开源、免费的、轻量化的、Java技术开发的一款接口测试工具、性能测试工具;
作为客户端通过大量网络协议向服务器发请求,可以测试目前业内主流的接口;由于能够模拟大量虚拟用户VU(Java多线程Thread技术实现),可以发起压力测试,可用测试系统的性能;
Java程序需要JVM Java虚拟机执行,JVM是一个进程 Process
如果后续要启动多任务,一定是Java的多线程技术 Thread 节省系统资源(轻量化)
计算机资源分配技巧:一般在一个进程中开启多个线程,而不是通过启动多个进程来模拟多任务。
快速提高技能的思路:多分析、思考测试工具、框架为何如此设计?
2、安装和使用JMeter
1)安装JDK:目前JDK1.6或1.8 Java开发工具包
(高版本JMeter 比如5.3要求1.8以上)
含有JVM Java虚拟机 程序,执行Java程序
设置系统环境变量:
JAVA_HOME JDK的安装目录
建议从实际JDK路径名拷贝,
比如:C:\Program Files (x86)\Java\jdk1.6.0
Path 命令的搜索路径
%JAVA_HOME%\bin;原有配置内容...
检查:cmd
set java_home
set path
java -version
2)安装JMeter:解压即可 apache-jmeter-2.12.zip
目录结构:
<1> bin目录:常用命令
jmeter.bat 给Windows使用 批处理
jmeter.sh 给Linux使用 shell脚本 Java跨平台
<2> lib目录:第三方类库 jar包
比如需要数据库驱动程序,将jar包放入lib中;
mysql.jar
启动:运行jmeter.bat 出现界面,关键:测试计划
原理:可以将一次测试计划配置到界面中(更直观);
保存后,是jmx文件,就是xml风格(便于存储复杂信息)
XML文件的第一行声明:
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan ...> 根标记:JMeter的测试计划
嵌套添加其他节点,配置计划中的内容
</jmeterTestPlan>
面试题:系统、产品中常见的配置文件有哪些格式? 触类旁通
jmeter.properties 属性文件 特点:大量的名值对 注释#开头
#配置端口号
#name=Tom
port=8000
name=测试计划
xxx.json JSON文件 {"名称": 值, ...}
server.xml XML文件 大量标签、属性存储信息
比如:修改过Tomcat的默认端口号为8880
.jmx 也是XML风格
3、面试题:JMeter的一个测试计划中有哪些要素? 先整体,后局部
1)根节点:测试计划 是其他节点的“容器”
配置内容:
用户定义的变量:配置计划中全局变量
名称和值 后续使用:${变量名} 区别{LR变量名}
name Tom ${name} 获取值Tom
独立运行每个线程组:一般不选
如果选中,多线程组会串行执行,测试性能时不够真实;
一般测性能时,多请求分别发送执行(并发)
如果需要顺序执行,则选中;
Add directory or jar to classpath: 类路径中添加jar包
比如访问数据库,需要数据库驱动程序 mysql.jar
添加第三方类库;(工具lib目录下也可)
2)测试计划下,添加1个或多个线程组:Thread Group
线程组可以配置1个或多个线程,模拟1个或多个用户;
测试功能时:1个VU 调试时,先使用1VU运行,分析执行轨迹,再转多VU
测试性能时:多个VU 发起更大的压力
在取样器错误后要执行动作:
一般选继续、有时可停止线程
线程数:1 模拟1个虚拟用户VU
Ramp-UP Period(in seconds): 1 用户准备时间
1个VU在1秒内做好准备(运行前初始化)
循环次数:默认1
调度器:一般不选择,正常执行完
若选中,出现调度器配置: 类似LR中的Duration持续时间
A.启动时间:2020/07/11 17:00:00
B.结束时间:2020/07/11 17:01:00 前两个为基础
C.持续时间(秒):180秒 优先3分钟 后两个调整 00~03
D.启动延迟(秒):120秒 延迟2分钟启动 02~05
3)线程组下,添加取样器Sampler: 常用协议的请求
目前:Http请求 按照接口文档、测试用例要求设置细节
名称:通用酒店数据-HTTP-GET-001
注释:基于HTTP协议,以GET方法,使用有效关键词kw发送请求,查看是否返回正确的JSON结果
服务器名称或IP:api01.idataapi.cn
端口号:8000
协议:HTTP
方法:GET
路径:/hotel/idataapi
第1个/代表Web应用程序的根目录
从端口号后算起
接口文档的URL参考:
http://api01.idataapi.cn:8000/hotel/idataapi
协议 域名 端口 应用资源路径
同请求一起发送的参数:添加
kw: 广州
apikey: xxxxxx
4)测试计划下或线程组下,添加“监听器” Listener (观察者模式)
不同位置添加作用域不同,在测试计划下添加,是对整个计划下内容进行监控;线程组下添加,只对当前组内监控;
<1> 察看结果树:和功能查看有关 请求包、响应包的关系
类似于LR的Tree树视图(HTML View网页效果,HTTP View协议数据包)、Fiddler的监控面板--审查 Raw选项卡
查看视图:Text 普通文本
HTML 网页页面效果 更直观
JSON JSON格式化后效果
<2> 图形结果:查看性能变化趋势
<3> 用表格察看结果:查看性能结果明细
<4> 聚合报告:查看性能结果统计
和Postman对比:
Postman的一个用例集,类似于JMeter中的一个测试计划,计划下可以创建1个或多个线程组,组中管理1个或多个请求;一条用例可以由1条请求或按照顺序执行的请求(顺序流)形成;
练习:对天气预报接口进行测试,使用GET方式
访问接口地址 语法 异常 非法 字符
java.net.URISyntaxException: Illegal character in authority at index 7: http://apis.juhe.cn :8000/simpleWeather/query?
Http主机连接 异常
org.apache.http.conn.HttpHostConnectException: Connection to http://apis.juhe.cn:8000 refused 被拒绝
练习:对中文分词接口进行一次测试,使用POST方式
api01.idataapi.cn
8000
HTTP
POST
/nlp/segment/bitspaceman
http://api01.idataapi.cn:8000/nlp/segment/bitspaceman
参数:
text
apikey 此处不妥!属于Post方式 请求主体中携带
{"message":"No API key found in headers or querystring"}
问题1:请求头部、查询字符串中未找到apikey
解决:在路径名后添加QueryString
/nlp/segment/bitspaceman?apikey=xxx
设计思路:开发者设计程序时,经常为程序出现的错误设计一些类,表示程序的异常XxxException、错误XxxError,在程序运行程序出现问题时抛出(throw),提示给开发者、测试者,及时发现问题;同时建议打开调试日志,便于查看结果。
问题2:java.util.zip.ZipException: Not in GZIP format
Zip异常 不是GZIP格式
原因:请求的头部信息不够完整,没有说明使用什么格式提交;--分析协议的数据包
解决:在线程组下添加“配置元件” -> HTTP信息头管理器
添加:名称 值
Accept-Encoding gzip,defalte
是浏览器发给服务器,声明浏览器支持的编码类型
其他问题:
URISyntaxException: Illegal character in query at index 84...
请求路径 语法 异常 非法 字符 在 下标位置
4、如何添加检查点? 也称为“断言” Accert 给出预期结果,对比实际结果
目的:自动化执行过程中,对结果进行检查,确保业务准确
LR:
1)找到相应请求:请求后的响应结果需要检查
先发送该请求,会返回响应结果,结果中文本需要检查
因 果
技巧:使用Tree视图 HTML View(页面视图)
找到响应快照 和 请求的对应关系
2)在相应请求之前写检查点函数:(通过关键右键生成)
reg注册性函数 要求写在相应请求之前
web_reg_find("Text=响应包需要检查的文本", LAST);
JMeter:
1)找到相应请求:导致其响应结果需要检查的那个请求
目前:就是自己编写的某请求,结果返回json等需要检查
其他:如果发请求,返回HTML网页,
结合监听器--察看结果树 HTML视图查看
网页效果和请求的关系 类似:LR的Tree视图(HTML视图 网页效果)
2)在相应请求下,添加“断言” -> 响应断言
1.要测试的响应字段:响应文本
2.模式匹配规则:包括
3.要测试的模式:北京
就是要检查的文本,注意:必须写响应包的源代码文本(协议数据包文本)
3)在测试计划或线程组下,添加“监听器”->断言结果
响应断言 : Test failed: text expected to contain /呵呵/
代表结果无法查到文本
添加1:检查响应码为200
名称:响应断言-HTTP响应码
注释:对HTTP响应码进行检查
测试字段:响应头 HTTP响应码在响应的头部信息中
模式匹配规则:包括
测试模式:200
就是需要检查的文本,点击添加
添加2:检查响应文本中含有:城市名称 比如北京
名称:响应断言-响应文本
注释:检查响应文本中含有:城市名称
测试字段:响应文本 就是响应主体文本内容
模式匹配规则:包括
测试模式:北京
练习:针对天气预报接口发送一条无效数据请求,并添加检查点(响应码、响应文本);
在线程组下新建:
请求名称:根据城市查询天气-HTTP-GET-002
描述:基于HTTP协议,以GET方法,使用无效的城市名查询天气,查看是否返回含有提示信息的JSON文本;
HTTP
apis.juhe.cn
GET
/simpleWeather/query
参数:
city 火星
key ${key}
http://apis.juhe.cn/simpleWeather/query?city=火星&key=xxxx
{"reason":"暂不支持该城市","result":null,"error_code":207301}
技巧:可以将HTTP响应码断言 拖拽到“线程组”下,能够对线程组下所有的请求负责,都要检查响应码为200;(共享方式)
在002请求下,再添加响应断言,对响应文本检查,要求含有:207301
名称:响应断言-响应文本
注释:检查响应文本含有:207301
测试字段:响应文本
模式匹配规则:包括
测试模式:207301
{"message":"API rate limit exceeded 并发已达上限","retcode":"100703"}
HTTP响应码:429 太多的请求 Too many requests!
技巧:让请求之间适当保留一些间隔时间!
比如Postman的批量执行,设置Delay 请求的延迟时间
越是大家都有的,越重要!
练习:使用JMeter对手机号码归属地接口进行测试。
1、设计、编写用例
前提:需求、接口文档 来源:juhe
功能介绍 / Introduction
根据手机号码或手机号码的前7位,查询手机号码归属地信息,如省份 、城市、运营商等。
手机号格式:一共11位 344结构
前7位就能够确定 哪个运营商、哪个地区
138-1181-0099
运营商-归属地-不同用户区分
三大:
中国移动 北京
中国电信
中国联通
搜索:常见运营商和号段
中国电信号段:
133、149、153、173、177、180、181、189、199
中国联通号段:
130、131、132、145、155、156、166、171、175、176、185、186、166
中国移动号段:
134(0-8)、135、136、137、138、139、147、150、151、152、157、158、159、172、178、182、183、184、187、188、198
接口地址:http://apis.juhe.cn/mobile/get
返回格式:json/xml
请求方式:get
请求示例:http://apis.juhe.cn/mobile/get?phone=13429667914&key=您申请的KEY
请求参数说明:
名称 必填 类型 说明
phone 是 int 需要查询的手机号码或手机号码前7位
key 是 string 在个人中心->我的数据,接口名称上方查看
dtype 否 string 返回数据的格式,xml或json,默认json
返回JSON结果:
{
"resultcode":"200",
"reason":"Return Successd!",
"result":{
"province":"浙江",
"city":"杭州",
"areacode":"0571",
"zip":"310000",
"company":"中国移动",
"card":""
}
}
2、编写用例
1)手机归属地查询-HTTP-GET-001
描述:基于HTTP协议,以GET方法,使用11位有效的手机号查询归属地,返回JSON格式的结果;
2)手机归属地查询-HTTP-GET-002
描述:基于HTTP协议,以GET方法,使用7位有效的手机号查询归属地,返回XML格式的结果;
3)手机归属地查询-HTTP-GET-003
描述:基于HTTP协议,以GET方法,使用无效的手机号(为空)查询归属地,返回JSON格式的结果;
比如:不填(长度为0的字符串)
预期结果:响应码200
响应文本含有:201101 手机号码不能为空
实际结果:
{
"result": null,
"reason": "The phone number can not be empty!",
"error_code": 201101,
"resultcode": "201"
}
4)手机归属地查询-HTTP-GET-004
描述:基于HTTP协议,以GET方法,使用无效的手机号(位数不够)查询归属地,返回JSON格式的结果;
比如:138118 6位,不够7位
预期结果:响应码200
响应文本含有:201102 错误的手机号码
实际结果:
{
"result": null,
"reason": "Wrong phone number!",
"error_code": 201102,
"resultcode": "202"
}
5)手机归属地查询-HTTP-GET-005
描述:基于HTTP协议,以GET方法,使用无效的手机号(错误的)查询归属地,返回JSON格式的结果;
比如:8110081 7位,但无效
预期结果:响应码200
响应文本含有:201103 查询无结果
实际结果:
{
"result": null,
"reason": "Empty",
"error_code": 201103,
"resultcode": "203"
}
3、使用JMeter执行用例
1)新建“测试计划”:手机号码归属地接口测试计划
(作为根节点!是其他子节点的最顶层容器)
描述:根据手机号码或手机号码的前7位,查询手机号码归属地信息,如省份 、城市、运营商等。
Test Plan
建议:在“测试计划”中设置全局变量,比如key
变量名 变量值
key xxxxxx
2)在“测试计划”节点下,新建“线程组” Thread Group
目前先测试功能,使用1个线程即可
Sampler
3)在“线程组”下,添加“取样器”:“HTTP请求”
比如:
名称:手机归属地查询-HTTP-GET-001
描述:基于HTTP协议,以GET方法,使用11位有效的手机号查询归属地,返回JSON格式的结果;
协议:HTTP
服务器名称:apis.juhe.cn
端口号:
方法:GET
路径:/mobile/get
默认采用:跟随重定向
同请求一起发生参数:
名称: 值:
phone 13811810099
key ${key}
dtype json
Listener
4)在“测试计划”下,添加“监听器”:察看结果树
发送请求,观察结果:Text或JSON视图
{
"result": {
"zip": "100000",
"province": "北京",
"city": "北京",
"company": "移动",
"areacode": "010",
"card": ""
},
"reason": "Return Successd!",
"error_code": 0,
"resultcode": "200"
}
4、针对HTTP响应码200,添加检查点:
1)找到相应请求 都是
在线程组下添加,能够为组下的所有请求的结果进行检查
2)在“线程组”下,添加“断言”:“响应断言”
名称:响应断言-HTTP响应码
注释:检查HTTP响应码为200
测试字段:响应头 因为HTTP响应码在响应的头部
模式匹配规则:包括
测试模式:200
自定义失败消息:HTTP响应码不是200!
3)在“测试计划”下,添加“监听器”:“断言结果”
观察执行效果:
如果只显示请求名称,表示检查通过;
如果显示请求名称和错误提示,表示检查失败!
5、针对响应文本进行检查
1)找到相应请求 比如001
在哪个请求下添加,就为哪个请求负责
2)在001请求下,添加“断言”:“响应断言”
名称:响应断言-响应文本
注释:检查响应文本中含有城市名称、运营商名称
测试字段:响应文本
描述匹配规则:包括
测试模式:添加两行 等待检查的文本
北京
移动
自定义失败消息:未查到预期城市名、运营商名!
改进:将以上断言分解为两个断言,分别检查,分别给出错误提示!
3)添加“监听器”:断言结果 就绪
6、针对005请求添加文本检查点,检查含有:201103
名称:响应断言-响应文本-错误编码
描述:检查响应文本含有错误编码:201103
补充:设置系统环境变量
1)新建JMETER_HOME
含义:JMeter的安装目录,供后续借用
比如:
变量名:JMETER_HOME
值:E:\apache-jmeter-5.3
2)修改Path
含义:命令的搜索路径
变量名:Path
值:原有的值;E:\apache-jmeter-5.3\bin
或:原有的值;%JMETER_HOME%\bin
目的:在cmd命令行中任何位置都能通过执行jmeter命令启动JMeter执行。
5、在自动化测试中如何添加步骤的等待时间?(面试题)
目的:让步骤有秩序的执行,符合业务的需要;
模拟平时用户的操作步骤间隔,更真实;
测试性能时可以通过调节间隔时间调节施压大小:时间越长,对服务器的压力会越小;
工具环境 代码或命令 语法
1)LR:lr_think_time(秒数); 类C 性能自动化
2)QTP:wait(秒数) VBScript UI功能自动化 基于页面控件
3)Selenium: sleep(秒数) Python UI功能自动化
4)Appium: sleep(秒数) Python 手机自动化
5)Java: Thread.sleep(毫秒数); Java
6)Linux: sleep 秒数 Linux shell命令 shell脚本
7)monkey: adb shell monkey ...--throttle 毫秒数 选项
8)monkeyrunner: MonkeyRunner.sleep(秒数) Python(Jython)
使用了类 API 使用Java语言实现的一套Python
随机算法:达到随机效果的规则、依据;
9)JMeter: 定时器Timer
效果:在某个请求下添加定时器,会在该请求发送之前等待一段时间;在线程组下添加定时器,组下所有请求都受影响,在请求之前都会等待;多处添加形成累加效果;
<1> 固定定时器:固定等待一段时间(时间更准确)
<2> 高斯随机定时器:按照高斯定理(正态分布)进行随机等待;(显得更真实)
正态分布:多个数据按照正态分布曲线进行概率分布
--随大流 满足大概率事件
偏差(毫秒):1000
固定延迟偏移(毫秒):3000
效果:以3秒为中心,前后偏移1秒为范围,满足正态分布
越靠近3秒的概率越高,越远离3秒的概率越低;
墨菲定律:越不太可能发生的事情有时容易发生。
(幂律分布)
面试题:接口的单点测试和流程测试?
单点测试:针对某接口进行一次访问 对应一条URL和参数
流程测试:将业务流通过多次请求依次访问,依次发送多条URL和参数
额外问题:上一次请求的结果数据,作为下一次请求的参数,需要采用“关联”技术解决!
用途:进行流程测试时,可以在请求之前适当间隔,一般采用随机间隔(高斯随机定时器),如果要求时间固定时,可以采用固定定时器。
比如执行某请求后,需要适当等待,后续请求才发送,保证业务完整性。
生活中 计算机中
透明: 看得见 看不见
透过看见 看不见其存在
同步: 同时做 先后做
<3> 同步定时器:Synchronizing Timer 用于并发测试,作为集合点!
JMeter或LR模拟 多线程模拟多用户(虚拟用户)
并发测试:模拟多用户在几乎同一时刻一起向服务器发送请求,模拟瞬时压力,观察系统各项性能指标是否符合性能需求。(平均响应时间 < 2秒)
(TPS 每秒事务数 达到一定标准)
日活:30万 一天时间完成30万笔交易、事务
300000 / 24*60*60 = 3.47笔/秒
结合二八原则:80/20原则
80%的交易发生在一天20%的时段内:
300000 * 0.8 / 24*60*60 * 0.2 = 13.8笔/秒
同步:等待A任务完成后,B任务才能开始 随同
和多线程、多用户有关
并发测试?等待所有VU到达集合点时一起释放;
在多线程开发中,同步技术能够解决线程安全问题;
--开发中的难点
Java中的关键字:synchronized 同步关键字
synchronized {
//同步代码块 同时只能允许一个线程执行
原理:哪个线程进入执行,获取锁标记(钥匙) 同步锁机制
其它线程无法进入执行;
只有归还了锁标记,才能让其它线程执行;
}
异步:A任务正在执行,B任务也可开始 异步请求
6、如何进行一次并发测试?(重要面试题)
含义:多用户在几乎同一时刻对某功能点进行瞬时访问,形成严格的并发操作;关键:集合点
LR:
1)Action脚本中添加事务; 目的:事务指标、并发的起点
2)事务开始之前添加集合点: 目的:形成严格的并发
lr_rendezvous("集合点名"); 可以同时管理多个集合点进行分别并发
lr函数比较通用,不同协议的脚本都可使用
3)控制台场景中设置并发策略: 目的:设定并发的规模
比如:让所有VU的100%到达集合点时一起释放;
或正在运行用户的100%
或直接指定用户数
并设置超时时间,超过该时间,就不等待,先并发执行;
需求:对天气预报接口进行n用户的并发测试
3
测性能建议使用内网测试,没有网络安全的限制
JMeter: 技巧:同步定时器 Synchronizing Timer
同步,具有“等待”之意 蓄势待发
1)找到开始并发的请求; 目的:并发的起点
2)在请求节点下,添加子节点:“同步定时器” 目的:集合点
多用户(线程)到达该请求时会等待(同步机制)
等待到齐后一起并发执行
定时器 -> Synchronizing Timer
1.名称:同步定时器
2.注释:作为并发测试的集合点
3.模拟用户组的数量:默认0 并发用户数参考线程数
表示所有线程都参与并发
期待并发的用户数:3 表示期望要求3个用户并发
要求线程组的线程数与之对应
4.超时时间(毫秒):10000
先到达集合点的VU开始计时,如果超过10秒,就不再等待,先并发执行已到达的VU;
3)线程组中设置合理的线程数:3 模拟VU,要足够
4)在线程组下添加和性能有关的监听器
图形结果:性能变化的趋势
用表格察看结果:每次请求性能明细
聚合报告:多次请求汇总统计
补充:对TPS的监听 目前JMeter5.3 添加了插件
可以添加新的监听器:Transaction Per Second
jp@gc - Transactions per Second
简称为TPS 每秒事务数
前提:对某请求设计为一个事务 Transaction
在“线程组”下,添加“逻辑控制器”:“事务控制器”
并将某请求移到“事务控制器”下,作为一个事务看待
练习:对用户登录操作进行100VU的并发测试,查看登录请求的平均响应时间,要求<3s(性能需求,提供一些指标,比如平均请求响应时间)
新建测试计划:testLogin.jmx
1)启动被测系统环境:Tomcat服务器 startup.bat
使用浏览器访问:
http://localhost:8880/web01/login.html
目前登录的请求是用访问页面模拟,未直接调用登录接口:
http://localhost:8880/web01/p1.html 返回页面模拟
协议 主机名 端口号 应用路径 资源名
方法:POST
参数:username Tom
password 123
2)使用JMeter配置测试计划,添加线程组、取样器
HTTP请求:
服务器名:localhost 端口号:8880
协议:HTTP 方法:POST
路径:/web01/p1.html 说明:真实的接口地址是一个虚拟路径 有后台代码实现
请求参数:username Tom
password 123
3)在请求节点下添加:同步定时器 Synchronizing Timer
配置期望并发用户数:0 表示希望全部线程并发
超时时间:10000 毫秒
4)线程组中设置合理的VU数:100
5)测试计划下添加监听器:
察看结果树、图形结果、用表格察看结果、聚合报告
如果需要TPS可以继续添加
测试结果对比:
请求响应时间=客户端时间+网络时间+服务器时间(Web DB ...)
并发用户数(个) 平均响应时间(秒)
100 0.188
200 0.443
300 0.818
...
1000 1.688
重要性能测试策略:递增测试
积累项目经验的技巧:__项目的__模块中,遇到__问题,经过分析,是__原因引起,凭借经验,是__解决的;类似的问题还有__;找其他项目,触类旁通
涉及业务:多分析业务需求
涉及技术:结合3W1H What? Why? Where? How?
概念 优势 应用场合 使用步骤、注意事项
123
字面量:1 100 56 "ABC"
变量:变量名不变,变量值可以改变
使用变量名 指代 变量的值
代词
系统变量:
变量名 变量值
JAVA_HOME xxxxx1.8
Path %JAVA_HOME%\bin;xxx;xxxx
add(a, b):
return a+b
以不变应万变!
变量名 变量的值
参数就是变量,加入的数据 avg(salary)
7、如何进行参数化?(变量化)
含义:将自动化脚本中的某些业务数据 变量化;
使用变量名 获取 不同业务数据;
目的:将脚本中的业务数据改变,满足更真实的用户体验;
某些需求中要求业务数据必须改变,比如:用户注册
用户名、手机号、邮箱号、文档重命名等不能重复
脚本必须要参数化,改变数据,才可使用
关键:类型 + 数据 + 策略
1)LR: 主要测试性能、也能测试接口,主要测试接口的性能
<1> 类型:File 使用文本文件存储数据 .dat文本文件
Date/Time 系统日期时间 指定不同格式 偏移
Random Number 随机值 指定范围
Unique Number 唯一值 确保多VU各自获取唯一数据
<2> 数据:性能测试要求数据真实、有效、合理
促成功能实现的基础上,考察性能问题
要么自己填写,要么关键设置规则自动产生
<3> 策略:取值方式 + 更新时机 超过值的策略
How? When? Out of Values?
SE组合:Sequential + Each Iteration
顺序 每次迭代
RE组合:Random + Each Iteration
随机 每次迭代
UEA组合:Unique + Each Iteration + Abort Vuser
唯一的 每次迭代 放弃虚拟用户
保证多VU各自取值互不相同
版本1:File类型 自己填写业务数据
版本2:Unique Number类型 感觉规则产生大量唯一数据
比如:注册大量手机号、上传大量文件 重命名不能重复
http://tool.chinaz.com/tools/urlencode.aspx
2)JMeter: 参考 类型+数据+策略
了解:常用类型
<1> 在测试计划中设置全局变量 比如key
优点:全局可用,整个计划共享
缺点:值一次只有一个,过于单一
<2> 使用“配置元件”:CSV Data Set Config
CSV数据设置配置
优点:数据自己准备、可定制,大批量使用
缺点:工作量较大
<3> 使用“函数助手”:生成不同功能函数,获取数据
优点:获取方便,功能丰富
需求:对请求的参数数据进行改变,比如查询中文文本、城市信息...
<1> 找到需要参数化的位置,比如提交的请求参数值
<2> 选择类型:文本文件,并提供文件数据 data
对比:LR: user.dat文件 普通的文本文件,扩展名改为dat
username,password 第一行是列名
jojo,bean 第二行开始才是数据
qq,123
| <-- 光标应该在最后一行数据的下一行开头
ctrl+a 全选文本 检查格式
JMeter: user.txt文件 不需要列名
jojo,bean 第一行开始就是数据
qq,123
| <-- 光标应该在最后一行数据的下一行开头
新建文本文件
比如:E:\text.txt 数据文件存储的路径名不要有中文、空白 否则影响读取
今天天气不错,今天
继续接口测试,接口
| <-- ctrl+a 光标应该在最后一行数据的下一行开头
说明:第1列表示需要提交的 分词文本
第2列表示分词后含有的文本 需要检查
E:\city.txt
北京
上海
深圳
说明:仅1列,表示城市名称
没一行供每次迭代、每个VU使用
<3> 在线程组下添加“配置元件” -> CSV Data Set Config 数据设置配置
说明:在谁之下添加,作用域就在谁之下
线程组下添加,组内的请求都可共享使用
1.Filename: E:\text.txt
文件路径名 绝对路径、相对路径(相对于当前计划文件 和jmx并列)
查看JMeter运行日志,查找问题原因
引起问题原因: 非法 参数 异常
Caused by: java.lang.IllegalArgumentException: File city.txt must exist and be readable 文件city.txt 必须存在 和 可读的
将city.txe文件 放在和jmx文件同样的目录下,就可使用相对路径,直接写city.txt
2.File encoding: 默认不写 或 UTF-8
根据实际需要也可以:UTF-8、GBK、GB2312
指定 文件字符编码 根据实际项目进行设置
3.Variable Names: text,check
后续请求通过${text} ${check}取值 LR没有$
变量名,就是后续请求中的变量名、参数名
多列使用逗号分隔,列的顺序和文件中列的顺序一致
比如登录:username,password
后续取值方式 ${username} ${password}
4.Delimiter: ,
分隔符,默认逗号
循环 在 End Of File 文件结束
5.Recycle on EOF?: True 可以循环重复使用数据
循环使用数据 文件结束时
6.Stop thread on EOF?: False
当文件结束时是否结束线程(VU) 工具通过线程模拟用户
用途:当多用户要求获取不同数据时,需要适可而止
唯一策略,如同放弃VU
7.Sharing mode: All threads
共享策略模式 多线程,依次向下交替使用数据
VU1: a1
VU2: a2
VU3: a1
VU4: a2
<4> 将请求中的固定数据改为参数: ${参数名} 类似JSP中EL表达式
比如:中文分词技术 -> ${text}
响应断言 : Test failed: text expected to contain /中文/
<5> 检查点中有相关的参数也需要更改;
比如:将 中文 -> ${check}
常见问题解决方法:
文件路径名、变量名是否一致、数据内容是否一致、策略细节是否合适、字符集UTF-8
java.net.UnknownHostException: api01.idataapi.cn
未知的主机 异常
路径名 语法 异常
java.net.URISyntaxException: Illegal character in authority at index 7: http://api01.idataapi.cn :8000/nlp/segment/bitspaceman?apikey=
响应断言 : Test failed: text expected to contain /${check}/
错误 从运行日志Log中查看: 文件 找不到 异常
ERROR - jmeter.config.CSVDataSet: java.io.FileNotFoundException: C:\Users\tren\Desktop\day07\city.txt (系统找不到指定的文件。)
练习:针对邮编查询地名请求进行参数化
思路:需要的参数?
邮编 页码 每页条数 结果类型 检查的城市名
postcode,page,pagesize,dtype,city
数据文件:E:\postcode.txt
或在jmx共同的目录下,新建postcode.txt
后续使用相对路径
postcode,page,pagesize,dtype,city
100080,1,5,json,北京市
201101,2,3,json,上海市
215001,1,3,xml,苏州市
邮编查询地名-HTTP-POST-001
基于HTTP协议,以POST方法,使用有效的一组数据,包括邮编、页码、每页记录条数、返回格式类型查询地名,查看是否返回正确的结果
URL:
http://v.juhe.cn/postcode/query
HTTP
v.juhe.cn
POST
/postcode/query
设置参数:
postcode 215001
key ${key}
page 1
pagesize 5
dtype json
思路:先将一个基础例子配置好后,再批量使用
后续添加检查点
HTTP响应码 200
响应文本:对应的城市名
对业务数据进行参数化
类型:配置元件 CSV Data Set Config
文件名:postcode.txt 相对路径
文件编码:默认不写
变量名称:postcode,page,pagesize,dtype,city
忽略首行:True
后续默认
修改请求中参数:
${postcode}
${page}
${pagesize}
${dtype}
修改文本检查点中内容:
${city}
面试题:Postman如何进行参数化?
思路:参数化也叫变量化,是将自动化脚本中的业务数据使用参数、变量替代,结合数据和策略控制取值方式,为了让业务更真实、并且符合某些特殊业务的需要,比如注册的用户名是不能重复;当前Postman通过一个请求,批量发送不同数据,减少用例的数量;
实现方式:
1)全局变量:
Postman右上角“环境管理”按钮 Manage Environments
全局Globals -> 输入变量名 和 变量值 -> 保存Save
后续使用数据时:{{变量名}}
对比:LR: {变量名}
JMeter: ${变量名}
Postman: {{变量名}}
目的:将以往多条用例合并,不同的数据通过一条用例逐个使用
也可以:通过代码设置全局变量
在Pre-request Script选项卡中设置: 请求之前的操作
postman.setGlobalVariable("key", "xxxxx");
设置 全局 变量 变量名 变量值
或
pm.globals.set("sj_key", "xxxxxx");
属于JS语法
2)使用文档进行参数化:支持txt、json、csv文件格式
以JSON文本格式为例:
<1> 新建phone.json,编辑:要求以数组方式存储数据,并且注意保存文本采用合适的字符编码集,推荐:UTF-8
[
{"phone": "13811810088", "city": "北京", "company": "移动"},
{"phone": "1330088", "city": "上海", "company": "电信"},
{"phone": "13000661199", "city": "广州", "company": "联通"}
]
<2> 将请求中业务数据使用参数代替:{{phone}}
<3> 针对用例集 -> 菜单Run窗口
Select File 选择文件:指定phone.json
自动识别 文件格式类型:application/json
由于数组中有三条数据,工具会自动修改为迭代3次 Iterations
建议设置请求间隔:1000ms 就是1秒
技巧:可以通过Preview 预览数据效果
Run运行该用例集
注意:检查中的业务数据也需要跟着改变
json文本保存编码格式也需要统一,比如另存为UTF-8
技巧:检查点中如何获取参数? tests选项卡的代码 JS语法
JS局部变量 根据参数名获取参数值 从phone.json文件中
city = pm.variables.get("city");
company = pm.variables.get("company");
tests["响应主体含有:北京"] = responseBody.has("北京");
改为:
tests["响应主体含有:" + city] = responseBody.has(city);
tests["响应主体含有:" + company] = responseBody.has(company);
思路:如何准备数据?
结合手工测试在界面中填写的业务数据,考虑有效、无效、必填、选填、数据边界值、各种条件的组合等,设计参数化数据,供工具自动执行,并且对结果进行有针对性的检查。
练习:针对邮编查询接口,基于HTTP协议,以POST方法,采用有效数据根据邮编查询城市信息,采用参数化技术。
邮编查询地名-HTTP-POST-001
基于HTTP协议,以POST方法,采用有效数据根据邮编查询城市信息,采用参数化技术。
参数化数据文件:postcode.json 另存为,指定UTF-8
[
{"postcode": "100080", "page": "1", "pagesize": "3", "city": "北京市"},
{"postcode": "215001", "page": "2", "pagesize": "3", "city": "苏州市"},
{"postcode": "201500", "page": "1", "pagesize": "5", "city": "上海市"}
]
技巧:通过在线JSON校验工具检查语法格式
https://www.json.cn/
安装好Mysql5 Mysql早期被Sun公司(Java)收购,后来Sun被Oracle收购!
mysql-5.0.18-win32.zip 解压后:Setup.exe
选择Skip跳过注册
默认端口号3306 如果冲突可以更改比如3308
指定数据库字符集:第3项 选为utf8 和UTF-8等同
可以将mysql的命令路径bin目录添加到PATH中
指定数据库密码,比如:123456
Execute 执行后全部显示对勾,表示成功!
如何查看数据库端口号?
cmd中:netstat -ano|more
回车:跳行 空格:翻页 q:退出
找到 3306 对应 pid进程号
根据任务管理器根据pid找到对应进程 mysqld.exe
如果安装失败,需要:
<1> 先卸载mysql 控制面板->添加与删除程序 卸载MySQL Server 5.0
<2> 到C:\Program Files (x86)下,删除MySQL目录
<3> 最好重启系统
<4> 重新安装
查看哪些数据库:
show databases;
创建一个数据库:testing
create database testing;
选择使用某数据库:
use testing;
查看数据库中有哪些表:
show tables;
8、如何使用JMeter压测数据库? JDBC
1)原理
JMeter是Java开发,Java访问数据库技术规范:JDBC
Java DataBase Connectivity
Java 数据库 连接
本质:一套API、一套类和接口、编程规范
class interface
了解三方:演绎设计者、实现者、使用者 分工的效果
<1> 规范的制定者:Oracle SUN Java语言作者
前提:Java语言本身不具备访问数据库的可能
但是:通过设计(数据库驱动)接口interface,只有设计没有实现,是制定规范的好办法;由各大数据库产商实现;
<2> 规范的实现者:数据库产商 .class 类 字节码文件
公司 产品 数据库驱动类的实现 driver
Oralce Oracle10g 11g 12c 将类打包 ojdbc14.jar包
IBM DB2 db2.jar
Microsoft SqlServer
Mysql Mysql mysql.jar
...
<3> 规范的使用者:广大程序猿,包括JMeter作者、JMeter使用者
(Java程序)
效果:JMeter通过Java编程可以让工具连接和访问数据库
前提:既需要JDBC API: JDK中默认含有 java.sql包 接口和工具类 已经就绪
还需要数据库驱动类的实现:各种jar包
想连接哪种数据库,就需要对应的jar包
Mysql5 mysql-connector-java-5.1.7-bin.jar
Java程序、JMeter实现的程序
2)程序访问数据库需要哪些参数? (工具配置的重点)(面试题)
<1> 主机名(IP地址):localhost
目前数据库安装在本地主机,项目中其它机器需要IP地址
如果Mysql安装在其他主机中,就写IP地址,确保网络可达
<2> 数据库端口号:3306
使用netstat -ano|more 查看端口号对应关系
<3> 数据库名:testing
<4> 数据库用户名:root
<5> 数据库密码:123456
以上信息可以汇总为:
<1> URL:访问数据库资源的地址
jdbc:mysql://localhost:3306/testing
协议名 主机名 端口号 数据库名
<2> 数据库用户名:root
<3> 数据库密码:123456
<4> 数据库驱动类名:由数据库产商实现的程序 Java类名
com.mysql.jdbc.Driver 目的:让工具注册数据库驱动程序!
包名 类名
存在于数据库驱动:Mysql版 jar包中
mysql-connector-java-5.1.7-bin.jar
安放到:E:\driver下
目前在testing库建立表和数据:测试数据
drop table emp;
create table emp (
empno int(11) primary key,
ename varchar(10) not null,
job varchar(9)
);
insert into emp values(9001, 'Tom', 'CTO');
insert into emp values(9002, 'Mary', 'CFO');
insert into emp values(9003, 'Andi', 'COO');
insert into emp values(9004, 'Rose', 'CHO');
insert into emp values(9005, 'James', 'CSO');
commit;
select * from emp;
select empno, ename, job from emp;
-----Oracle 版本--------
drop table emp;
create table emp (
empno number(11) primary key,
ename varchar2(10) not null,
job varchar2(9)
);
insert into emp values(9001, 'Tom', 'CTO');
insert into emp values(9002, 'Mary', 'CFO');
insert into emp values(9003, 'Andi', 'COO');
insert into emp values(9004, 'Rose', 'CHO');
insert into emp values(9005, 'James', 'CSO');
commit;
select * from emp;
select empno, ename, job from emp;
Oracle的连接配置参数:
默认数据库名orcl
jdbc:oracle:thin:@localhost:1521:orcl
jdbc:oracle:thin:@localhost:1521:XE
oracle.jdbc.driver.OracleDriver
system
123456
查看Oracle数据库名: Oracle数据字典 查看内部信息
SQL> select name from v$database;
SQL> show parameter db_name;
结果:XE
观点:目前许多问题是从数据库层面发现的;
编写sql对数据库进行查看,看结果是否满足预期;
例子:下订单 对数据库哪些表有影响?
订单表、条目表、用户表、商品表、收货人表...
order item user product receiver
需求:对某条查询sql进行100~2000VU的并发测试,观察sql的平均响应时间,要求<1.5秒;结合递增策略
思路:JMeter具有访问数据库的能力(JDBC技术),能够发起并发压力
只要通过合理的配置,就能够达成一个测试计划
9、实现具体步骤:
1)新建测试计划 testJDBC.jmx
2)测试计划下新建“线程组”: 建议:先测试功能,再给压力测试性能
默认1个线程,先模拟1VU测试功能
3)在线程组下,新建“配置元件” -> JDBC连接配置
JDBC Connection Configuration
1.针对Mysql5数据库的连接配置
2.Variable Name: mysql5
变量名,就是对当前配置的代号,供后续请求选择使用
3.数据库URL:jdbc:mysql://localhost:3306/testing
4.JDBC数据库驱动类名:com.mysql.jdbc.Driver
5.数据库用户名:root
6.数据库密码:123456
4)在线程组下,添加“取样器Sampler” -> JDBC请求 JDBC Request
1.注释:针对一条查询sql的请求
2.Variable Name: mysql5
变量名,选择之前JDBC连接配置的 代号
3.SQL Query
Query Type: SQL的类型
<1> Select Statement:特指select语句 查询 (选择) 读操作 Disk Input 输入
结果就是查询的行、列内容
<2> Update Statement:泛指所有的更新 增、改、删 写操作 Disk Output 输出
insert、update、delete
结果是影响的记录条数 比如删除5条记录,返回5
可 调用
<3> Callable Statement:可调用的存储过程
对比:使用存储过程前后
不用:日常访问
WebServer -网络-> DBServer
接口程序
SQL 网络传输->翻译SQL->C程序->编译->连接->执行
<------ 查询结果
存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,它存储在数据库中,一次编译后永久有效,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象。在数据量特别庞大的情况下利用存储过程能达到倍速的效率提升;
使用:大大优化查询的性能
WebServer -网络-> DBServer
调用存储过程名 存储过程 提前编译好 等待调用
g1 ------------->
<------------ 查询结果
缺点:存储过程固化在数据库端,如果业务规则改变了,需要重新修改和布置存储过程,难以维护。适合于功能比较稳定、数据量较大、对性能有高要求的业务。
<4> Query: 写有效的sql语句,sql本身结尾没有分号
select * from emp
5)在测试计划下添加“监听器”:-> 察看结果树:
问题1:未添加数据库驱动程序
响应 消息 SQL异常 没有 合适的 驱动 找到
Response message: java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/testing
问题2:请求指定的连接配置名称不对
数据库变量名找不到
No pool found named: 'mysql6', ensure Variable Name matches Variable Name of JDBC Connection Configuration
问题3:SQL语句语法不对 比如from 和 form
来自 表单
SQL语法 错误
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'form emp' at line 1
表单
问题4:数据库或表名不对
testing数据库中没有emp1表 表也是数据库中的对象
Table 'testing.emp1' doesn't exist
未知的数据库 testing1
Unknown database 'testing1'
问题5:连接配置设置失误,比如URL地址、用户名和密码
Response message: 通讯异常 通讯连接失败com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
SQL异常,访问被拒绝 用户账户相关 有密码
数据库有关的异常
Response message: java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
6)在环境中添加数据库驱动:xxx.jar
方法1:在当前测试计划中添加 仅当前计划可用
在 “测试计划”中 -> 添加jar包到类路径下
通过“浏览” 选择合适的jar包:
E:\driver\mysql-connector-java-5.1.7-bin.jar
方法2:在JMeter工具中添加 以后所有计划都可用 一劳永逸
在JMeter的lib目录下,添加合适的第三方jar包
好处:所有测试计划共享这些资源;
注意:添加后,需要重启JMeter才生效;
7)在JDBC请求下,添加“定时器”:同步定时器
Synchronizing Timer
指定期望并发用户数:100、200、300、500、1000、2000
写成0 表示所有线程参与并发
超时时间(毫秒):10000 表示10秒
如果写0 表示无限期等待
8)线程组需要对应线程数: 结合递增测试策略进行 压力从小到大 逐步加压
100、200、300、500、1000、2000
9)添加和性能测试有关的监听器:
图形结果、用表格察看结果、聚合报告
平均响应时间:(毫秒ms)
75 87 101 124 767
结果大约0.1秒左右,随着压力增大,变化不明显,由于数据库中的数据量不大,并且查询语句逻辑简单,耗时较少;另外,明数据库很可能存在查询结果的缓存Cache(思想:拿空间换时间),能够尽快将结果呈现给用户;
思考:后续需要测试什么SQL?
后台接口程序,在需要从数据库中获取信息时,会通过程序向数据库发送执行SQL语句,随着业务复杂度提高,SQL语句也越来越复杂,比如涉及多表连接查询、子查询(查询嵌套)、海量数据中查询少量结果;此时对数据库的测试更有必要,有时需要测试人员自己编写SQL语句,和开发方查询结果进行对比。
既可以测试SQL的功能,又可以测试SQL的性能(大部分性能问题和数据库有关)。
练习:使用JMeter工具向emp表中添加5条员工信息
1)新建测试计划:testAdd.jmx
2)测试计划下添加线程组,默认1个线程
3)线程组下添加配置元件:JDBC连接配置
<1> 变量名(连接配置代号):mysql5
<2> 数据库URL:jdbc:mysql://localhost:3306/testing
<3> JDBC数据库驱动类名:com.mysql.jdbc.Driver
<4> 数据库用户名:root
<5> 数据库密码:123456
4)线程组下添加Sampler 取样器:JDBC请求
<1> 变量名(连接配置代号):mysql5
<2> SQL类型:Update Statement 更新语句
insert、update、delete都属于更新操作!都会改变数据库数据
<3> insert into emp(empno, ename, job) values(9006, 'Lucy', 'PM')
insert into emp(empno, ename, job) values(9006, '', '')
5)在测试计划下添加监听器:
察看结果树
第一次执行成功了;
第二次执行失败了:
Duplicate entry '9006' for key 1
Response message: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '9006' for key 1
MySQL完整性约束违反异常:密钥1重复条目'9006'
原因:违反了主键约束(实体完整性约束,就是唯一性)
主键PK primary key 唯一 且 非空
6)需要对数据进行参数化:
在线程组下添加配置元件:CSV Data Set Config 数据配置
<1> 数据文件路径:E:\emp.txt
<2> 字符集:不填 或 UTF-8 根据实际环境匹配
<3> 变量名:empno,ename,job
忽略首行:True
<4> 分隔符:默认逗号分隔
<5> Recyle on EOF: False 文件结束时不允许重复使用数据
<6> 文件结束时是否结束线程:True
<7> Sharing Mode共享模式: 默认All Threads
不同线程各自获取不同数据
在E:\下准备emp.txt,内容如下:
empno,ename,job
9007,Emp007,PM
9008,Emp008,SD
9009,Emp009,SD
9010,Emp010,SD
9011,Emp011,TSD
|
7)将JDBC请求中的SQL的数据改为参数:${变量名}
insert into emp(empno, ename, job) values(${empno}, '${ename}', '${job}')
列举常用的函数助手:
<1> char 根据字符编码 生成 对应的字符
${__char(65)} A
${__char(66)} C
...
${__char(97)} a
<2> Random 根据数据范围生成一个随机整数
会将该随机数存于变量num中,供后续继续使用
${__Random(1,100,num)} 表示生成1~100内的随机整数
后续使用:
${num}
select ${__Random(1,100,num)}, ${num}
由于随机数可能会重复,不适合作为id值
<3> UUID 通用唯一识别码(Universally Unique Identifier)的缩写
能够生成大量唯一的长编号
${__UUID}
ebf12ea8-7a81-40ec-b1f9-1deaed7b9023
9f96f1ed-6816-4778-916f-ace42f706813
<4> counter 计数器 从1开始递增
${__counter(TRUE,num)} 每个VU从1开始取值
${__counter(FALSE,num)} 多VU共享使用递增数据
select ${__counter(TRUE,num)}, ${num}, ${num}
效果:
select 1, 1, 1
select 2, 2, 2
...
补充技巧:JMeter中具有“函数助手对话框” 生成一些函数
比如:__Random 生成随机数 比如1~100 变量名num
${__Random(1,100,num)} 后续${num}
比如:__counter 生成 自增序列 常用于数据库表中id的生成
TRUE: 不同VU局部拥有 VU1: 1 2 3 VU2: 1 2 3
FALSE: 不同VU全局共同拥有 VU1: 1 VU2: 2 VU3: 3 ...
${__counter(FALSE,num)}
${__counter(TRUE,num)}
insert into emp(empno, ename, job) values(${__counter(TRUE,num)}, '${ename}', '${job}')
insert into emp(empno, ename, job) values(${__counter(FALSE,num)}, concat('Emp', ${num}), '${job}')
Mysql中字符串拼接:concat函数
concat('Emp', 'hehe') 结果:'Emphehe'
concat('Emp', 123) 结果:'Emp123'
问题:Duplicate entry '2' for key 1
重复的
技巧:通过SQL改变后台数据,让数据不重复;
delete from emp where empno between 1 and 10;
面试题:如何向数据库中快速添加大量数据?
思路:自动化 工具、代码、SQL、参数化、循环...
比如:JMeter 通过配置执行 testadd.jmx
核心:JDBC规范、JDBC连接配置、JDBC请求
SQL分为:select和update
数据可以参数化:全局--测试计划
CSV数据配置
函数助手
10、如何进行在线综合场景测试?(混合交易测试)
模拟很多用户,不同用户执行不同任务,持续执行一段时间
对比:基准测试 1个线程,循环执行若干次
并发测试 n个线程,各自并发执行1次或n次
在线综合场景 n个线程,执行不同业务若干次、一段时间 混合交易
多用户、多任务、时间长
技巧:先调试好某任务,之后再重组
不同测试计划中的节点可以复制、粘贴,可以剪辑
重要细节:
<1> 测试计划设置为:不能选择“独立运行每个线程组”,除非不同组之间确实要先后执行
<2> 不同线程组设置相应的线程数,模拟不同VU
<3> 线程组中可以有1条或多条请求
<4> 线程组中设置“调度器”,可以设置场景运行的持续时间
录制 和 回放
Badboy JMeter
-> .jmx
11、使用Badboy工具为JMeter录制脚本
前提:有界面 使用浏览器访问Web服务器
1)Badboy是澳洲提供的一个录制脚本工具,尤其为JMeter提供了定制化的录制方案,简而易用、轻量、免费;
2)安装:BadboyInstaller-2.1.2.exe
运行默认下一步
3)录制:
先填写首页URL
http://localhost:8880/web01/login.html
执行正常业务操作,等待录制好(录制状态为蓝色)再下一步
录制结束点击Off,保存为.bb文件
导出为.jmx(File -> Export to JMeter)
4)使用JMeter打开jmx文件进行调试,发请求,查看结果;
后续可以对测试计划进行增强,比如检查点、定时器、集合点、配置元件...
练习:对百度的一次关键词搜索录制脚本,搜索:JMeter
https://www.baidu.com
面试题:两个接口之间如何协作?
业务需要依次访问不同接口,比如第1个接口返回的结果,需要作为第2个接口请求的参数,如何实现?
关键思路:脚本关联技术
之前请求返回的数据,作为后续请求的参数
(与有关的数据产生联系)
比如:JMeter使用 “后置处理器”:“正则表达式提取器”
<meta name="description" content="全球最大的中文搜索引擎
<meta name="description" content="全球(.*)的中文搜索引擎
结果:
{"q":"最大","p":false,"g":[{"type":"sug","sa":"s_1","q":"最大公因数和最小公倍数"},{"type":"sug","sa":"s_2","q":"最大霸王龙化石拍出天价"},{"type":"sug","sa":"s_3","q":"最大的自然数是多少"},{"type":"sug","sa":"s_4","q":"最大摄氧量"},{"type":"sug","sa":"s_5","q":"最大公约数"},{"type":"sug","sa":"s_6","q":"最大的猫头鹰"},{"type":"sug","sa":"s_7","q":"最大的两位数和最小的两位数差是多少"},{"type":"sug","sa":"s_8","q":"最大泡压法测定溶液表面张力实验报告"},{"type":"sug","sa":"s_9","q":"最大金矿老板"},{"type":"sug","sa":"s_10","q":"最大的负整数是多少?"}
安装好VMware
Linux安装文件:
shrike-i386-disc1.iso 638MB
shrike-i386-disc2.iso 646MB
shrike-i386-disc3.iso 485MB