GUI自动化测试工具模拟的是用户的界面操作,因此测试脚本记录的是用户在界面上对控件的操作,而性能测试工具模拟的是用户的客户端与客户端之间的通信协议和数据,这些通信协议和数据往往是用户在界面上执行GUI操作时产生的
正是由于脚本的模拟是基于协议的,所以我们才能比较方便的模拟成千上万并发用户同时使用系统的场景
GUI自动化测试的执行,一般是单用户执行并验证功能结果;而性能测试的执行,往往需要同时模拟大量的并发用户,不仅需要验证业务功能是否完成,还需要收集各种性能监控指标,涉及压力产生器、并发用户调度控制、实时监控收集等内容,所以性能测试执行控制要比GUI自动化测试复杂的多
主流web应用,基于http/https,web service应用,基于web service协议
把基于协议模拟用户行为的脚本称为虚拟用户脚本,把开发和产生这些脚本的工具称为虚拟用户脚本生成器
不同后端性能测试工具使用上区别比较大,loadrunner通过录制再修改的方式生成虚拟用户脚本,jmeter主要通过添加各种组件,然后对组件进行配置方式生成虚拟用户脚本
把实际发起测试负载的机器称为压力产生器,一台压力产生器能承载的虚拟用户数量是有限的,当需要的并发用户数超过了单台提供极限时,需要引入多台压力产生器合作发起需要的测试负载
有了多台产生器,就需要一个专门的控制器来统一管理与协调这些压力产生器,称为压力控制器
性能监控器的数据显示界面是性能测试工程师最密切关注的部分,性能测试工程师会根据实时的数据显示来判断测试负载情况下系统健康状况
不同的后端测试工具,系统监控器能力差距也比较大,如LoadRunner系统监控器很强大,支持收集各种操作系统的系统参数,还支持与SiteScope等第三方专业监控工具的无缝集成
后端性能测试工具通常能够基于该报告生成各类指标的各种图表,还能将多个指标关联在一起进行综合分析来找出各个指标之间的关联性,这部分工作模块称为测试结果分析器
并发用户数多少?
测试刚开始,以什么样的速率添加并发用户?如:每秒5个
达到最大并发用户数后持续多长时间?
测试结束后,以什么样的速率来减少并发用户?如:每秒5个
需要包含哪些业务操作,各个业务操作占比是多少?如,10%登陆,70%查询,20%订单
一轮虚拟用户脚本执行结束后,需要等待多长时间开始下一次执行?
同一虚拟用户脚本中,各个操作之间等待时间是多少?
需要监控哪些被测服务器的哪些指标?
脚本出错的处理方式是什么?如,错误率达到10%,自动停止该脚本
需要使用多少台压力产生器?
可以提供全方位的量化指标,包括页面加载时间、首字节时间、渲染开始时间、最早也买你可交互时间、页面中各种资源的字节数、后端请求数量等一系列数据
还能自动给出被测也买你性能优化水平的评价指标,哪些被优化哪些需要改进
1,访问主页
2,将被测页面的地址填写到被测Website URL中
3,选择被测发起的地域(Test location)以及希望使用的浏览器
webpagetest在全球都有测试代理机,可能是虚拟机,也可能是真机,还有很多是云端机器,webpagetest除了支持各种浏览器外,还支持主流android设备和apple设备
4,选择需要模拟的网络情况(可以选择有线网络cable,也可以3G/4G)
5,在Repeat View中选择打开 'First View and Repeat View' (既要测试第一次打开页面的前端性能First View,也要测试在有缓存情况下重复打开的前端性能Repeat View)
6,最后点击 'Start Test'发起测试,一般情况下不会立即执行,而是进入排队系统
7,测试执行完成后,会看到测试结果页面
指用户发起页面请求到接收到服务器返回的第一个字节所花费的时间,这个指标反映了后端服务器处理请求、构建页面,并且通过网络返回所花费的时间
可以查看下方耗时表格,First Byte项的first view和repeat view, 这两个指标应该控制在1秒以下
页面上的各种资源(图片,js,css等)都需要通过连接web服务器来获取,与服务器建立连接过程往往比较耗费时间,所以理想的做法的尽可能重用已经建立好的链接,避免每次使用都去创建新的链接
Keep-alive Enabled就是,要求每次请求使用已经建立好的链接,属于服务器上配置,不需要对页面做任何修改,启用keep-alive通常会将加载时间减少40%-50%,页面请求数越多,能够节省的时间越多
在测试结果 Performance Review中可以查看Keep-alive Enabled的统计结果 keep-alive
如果将页面上各种文本类资源(html, js, css等)进行压缩,将会减少网络传输的数据量,同时由于js和css都是页面上最先被加载的部分,所以减小这部分数据量也会加快页面的加载速度,同时也能缩短First Byte Time
为文本资源启用压缩通常也是服务器配置更改,无需对页面本身进行任何修改
在报告下方显示资源压缩情况
Use gzip compression for transferring compressable responses:
显示未被压缩的资源个数以及如果资源压缩后节省的传递数据量
在测试结果 Performance Review中可以查看Keep-alive Enabled的统计结果 Gzip
为了减少网络传输的数据量,蚊香文件也需要进行压缩处理,如果所有jpeg图片都没有经过必要的压缩处理,并且所有的jpeg图片都没有使用渐进式jpeg技术,那么就会给出D级评分
普通Jpeg:存储方式是按照从上到下的扫描方式,把每一行数据保存在jpeg文件中,打开这个文件显示他的内容时,数据按照存储时的顺序从上到下一行一行被显示,直至所有数据被读取完成,完成整张图片显示。如果文件较大或者网络下载速度较慢,就会看到图片是一行一行被加载的,为了更好的体验,出现了渐进式
渐进式jpeg: 包含多次扫描,然后将扫描顺序存储在jpeg文件中。打开文件的过程,会先显示整个文件的模糊轮廓,随着扫描次数的增加,图片会变得越来越清晰。这种格式主要优点是网络较慢时,通过图片轮廓可以知道正在加载的图片大致是什么,所以这种技术往往被用于一些网站打开一些较大的图片
在测试结果 Performance Review中可以查看Keep-alive Enabled的统计结果 Compress Img
一般情况下,页面上静态资源不会经常变化,所以如果浏览器可以缓存这些西元,当重复访问时,可以直接从缓存中读取已有的副本,而不是每次向web服务器请求资源,可以显著提升重复访问页面的性能,并减少web服务器的负载
CDN是内容分发网络的缩写,基本原理是采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的网络供应商机房中,当用户访问网站时,利用全局负载技术将用户访问指向距离最近的、工作正常的缓存服务器上,由缓存服务器直接响应用户请求
指的是浏览器开始渲染的时间,从用户角度看就是在页面上看到第一个内容的时间,该时间决定了用户对页面加载快慢的第一直观印象,这个时间越短用户会感觉页面越快,这样用户也会有耐心等待其他内容的展现。
理论上说,Start Render时间主要由三个部分组成,分别是 '发起请求到服务器返回到第一个字节的时间(first byte时间)','从服务器加载HTML文档的时间','HTML文档头部解析完成所需的时间',因此影响start render时间因素包括服务器响应时间、网络传输时间、HTML文档的大小以及HTML头中资源使用情况
可以简单理解为最早的页面可交互时间。页面可交互的内容,包括很多种类,比如点击一个链接、点击一个按钮都属于页面可以交互的范畴, first inetractive时间的长短对用户体验非常重要,决定用户对页面功能的使用,这个值越短越好
为了使这个值尽可能小,通常采用以下措施:
只有页面控件内容渲染出来了,才有可能进行交互,所以first interactive依赖于start render时间
尽可能将交互控件的代码放置在HTML BODY前部,让其尽早加载
尽早做js的初始化和绑定,目前做法有两种,一是DOM ready中做所有js初始化和功能绑定,二是在页面底部做js初始化和功能绑定
这两种做法优点在于简单,不需要关注具体DOM结点的位置,缺点在于初始化时间太晚,因此,应该将js初始化提升到相关DOM元素建立起来后进行
一般来说这个值也不要大于5S
严格来说,Speed Index是通过微积分定义的,理解起来会比较困难,这里只做定性讨论
影响网页性能体验的一个重要指标是页面打开时间,打开时间越短体验越好。但是,当存在两个打开时间完全相同的网站A/B时,其中网站A的打开过程是逐渐渲染页面完成的,而网站B的打开过程是空白了一段时间后在短时间内渲染页面完成的
WebPagetest API Wrapper是一款基于Node.js,调用了WebPagetest提供的API的命令行工具。也就是说,你可以利用这个命令行工具发起基于WebPagetest的前端性能测试,这样就可以很方便地与CI/CD流水线集成了。具体的使用步骤如下:
通过“npm install webpagetest -g”安装该命令行工具;
访问https://www.webpagetest.org/getkey.php获取你的WebPagetest API Key;
使用“webpagetest test -k API-KEY 被测页面URL”发起测试,该调用是异步操作,会立即返回,并为你提供一个testId;
使用“webpagetest status testId”查询测试是否完成;
测试完成后,就可以通过“webpagetest results testId”查看测试报告,但是你会发现测试报告是个很大的JSON文件,可读性较差;
通过“npm install webpagetest-mapper -g”安装webpagetest-mapper工具,这是为了解决测试报告可读性差的问题,将WebPagetest生成的JSON文件格式的测试报告转换成为HTML文件格式;
使用“Wptmap -key API-KEY --resultIds testId --output ./test.html”将JSON文件格式的测试结果转换成HTML格式。
Jmeter的官方文档对其使用方法介绍的很详细,操作基本属于 '傻瓜式'的,Jmeter难点在于:如何支持海量并发,以及实现更好的load控制(解决方法是参考loadrunner实现方式,然后从实际业务场景进行二次开发)
互联网企业和传统企业的软件产品的后端性能测试,原理以及基本方法是一样的,区别较大的只是全链路压测
关于互联网软件产品的全链路压测,由于需要实现海量并发以及流量隔离等操作,所以难度较大
首先通过虚拟用户脚本生成器生成基于协议的虚拟用户脚本,然后根据性能测试场景设计的要求,通过压力控制器控制协调各个压力产生器以并发的方式执行虚拟用户脚本,并且在测试执行过程中,通过系统监控器收集各种性能指标以及系统资源占用率,最后通过测试结果分析器展示测试结果数据
用于模拟用户行为的测试脚本,生成的手段主要是基于协议的录制,也就是性能测试脚本开发人员在通过GUI执行任务操作同时,录制客户端和服务器之间的通信协议,并最终转化为代码化的LoadRunner虚拟用户脚本
这样转化得到的虚拟用户脚本往往并不能直接使用,还需要经理数据参数化(Parameterization)、关联建立(Correlation)、以及运行时设置(Run Time Setting)等操作,才能用于性能测试场景中
Controller相当于性能测试执行的控制管理中心,负责控制Load Generator产生测试负载,以执行预先设定好的性能测试场景,同时还负责收集各类监控数据
在实际执行性能测试时,Controller是和性能工程师打交道最多的模块,性能工程师在Controller的UI界面上完成测试场景的设计、运行时的实时监控、测试负载的开始与结束等操作
是Loadrunner中一个强大的分析插件,不仅图形化展示测试过程中收集的数据,还很方便的对多个指标做关联分析,找到他们之间的因果关系。根本目的就是,分析系统可能的性能瓶颈点以及潜在的性能问题
1,性能需求收集以及负载计划制定;
2,录制并增强虚拟用户脚本;(Virtual User Generator)
3,创建并定义性能测试场景;(LoadRunner Controller)
4,执行性能测试场景;(controller)
5,分析测试报告。(LoadRunner Analysis)
一般情况下,企业级后端性能测试具体需求,主要包含以下内容:
系统整体的并发用户数
并发用户业务操作的分布情况
单一业务操作的用户行为模式
并发用户高峰期的实践分布规律
达到最高峰负载的时间长度
获取测试需求是性能测试中最难的两个工作之一,另一个工作是,测试结果分析和性能问题定位
因为大多数情况下没有人会告诉你具体的性能需求,一般产品经理会给出一个定性的描述,但是要转化为实际可操作的性能测试需求,还需要进一步细化
如:性能要求,每天支持完成8000个体检
首选需要明确,这里的每天是否是24小时
明确了8小时后,那么原始需求是不是可以转化为每小时完成1000体检
最后采用20/80乐原则对于高峰时期的用户负载紧进行加密
在得到负载模型后,性能测试人员还会再chi1基础上加入一些冗余,如在峰值的基础上在再额外放大20%
1,识别被测应用使用的协议
2,录制脚本
3,完善录制得到的脚本(技术细节较多)
4,验证脚本的正确性
如果已经和系统设计、开发人员沟通过,明确知道了被测系统所采用的协议,可以跳过这一步
不知道的话,可以使用Virtual User Generator模块自带的Protocol Advisor识别被测应用使用的协议,具体流程:
1,在Virtual User Generator中依次点击File、Protocol、AdvisorAnalyze、Application,展开这些菜单。
2,在打开的界面上按要求填写被测应用的信息。
3,Protocol Advisor会自动运行被测系统。如果是网页应用,就会打开浏览器。
4,在页面上执行一些典型的业务操作,完成这些业务操作后点击"Stop Analyzing"按钮停止录制。
5,Protocol Advisor会根据刚才录制的内容自动分析被测应用使用的协议,并给出最终的建议。
接下来,就可以使用Protocol Advisor建议的录制协议开始脚本录制工作了
录制脚本的基本原理是,通过GUI界面对被测系统进行业务操作,Virtual User Genrrator模块在后台操作所触发的客户端与服务端的所有交互,并生产基于C语言的虚拟用户脚本文件
也就是说,录制脚本的过程需要通过GUI实际执行业务操作(录制脚本之前,熟悉GUI操作步骤,明确哪些步骤会对服务器发起请求)
知道哪些步骤发起请求的原因是,要将这些步骤在虚拟用户脚本中封装成 '事务'。封装为事务的目的是统计响应时间,因为loadrunner中响应时间都是以事务为单位的
具体步骤:
1,首先,选择Create/Edit Scripts进入Virtual User Generator创建脚本的协议选择界面。
2,选择正确的协议后进入Start Recording界面,选择需要录制的应用类型,并填写应用的详细信息。如果是Web应用,Application type就应该选择Internet Application,然后选择浏览器并填写这个Web应用的URL,完成后自动打开浏览器。
3,在该浏览器中执行业务操作,Virtual User Generator模块会记录所有的业务操作,并生成脚本。
在录制脚本过程中,强烈建议直接对后端调用的操作添加事务定义,而不要等到脚本生成后再添加,因为loadrunner脚本的可读性并不好,在录制完的脚本中添加事务定义的难度会很大
录制脚本过程中,直接添加事务操作也很简单,主要分为3步:
1,在开始执行GUI操作前,先点击图2中的“事务开始”按钮并填写事务名称;
2,执行GUI操作;
3,操作完成后,点击图2中的“事务结束”按钮
这样刚才执行的GUI操作脚本就会被Lr_start_transaction(事务名称)和Lr_end_transaction(事务名称, Lr_AUTO)包围起来,也就完成了事务的定义
脚本录制,只是虚拟用户脚本开发中最简单的一步,不能直接使用,还需要进一步处理:
1,在两个事务之间加入思考时间(Think Time);
2,对界面输入的数据做参数化(Parameterization)操作;
3,完成脚本的关联(Correlation)操作;
4,加入检查点(Check Point)。
这4步处理操作是虚拟用户脚本开发中最关键的地方,需要清楚为什么进行这些处理
1,在两个事务之间加入思考时间
思考时间是指:用户在实际使用中,并不会连续不断地向后端服务器发起请求,在两次发起请求之间往往会有一个时间间隔,这个时间间隔主要来自两个方面:用户人为等待时间;用户填写信息耗时
只需要直接调用Loafdrunner中的Lr_think_time()函数,就可以在两个事务之间加入思考时间,但是这个思考时间设为多少,并不容易知道
所以在一个项目中,一般先粗略估算一个值(如15s),然后在实际执行负载场景中,根据系统吞吐量调正
在后续调整思考时间时,无需逐行修改虚拟用户脚本代码,可以在Run-time-Settings中很方便完成
Run-time-Settings支持多种方式调整思考时间:
As recorded,代表直接使用Lr_think_time()函数中指定的时间
Mutiply recorded think time by,代表在lr_think_time()函数中指定时间基础上乘一个数字
Use random percentage of recorded think time,指使用思考时间范围内随机值
Limit think time to,指为思考时间设置一个上限值,只要lr_think_time()函数中时间没有超过,就按函数时间定
2,对界面输入的数据做参数化操作
如,录制的虚拟用户脚本是用户登陆操作,那么回放时需要多用户并发,要把脚本中用户名和密码独立出来,类似于数据驱动的自动化测试
LoadRunner支持的参数化数据源也很丰富,既可以是excel,也可以是数据库中的表
需要注意的是:参数文件中使用的测试数据在性能执行前事先准备好
所以参数化操作其实是两部分组成:
1,性能测试脚本和测试数据分离
2,事先建立的性能测试数据
3,完成脚本的关联操作
关联操作是LaodRunner虚拟用户脚本开发过程中最关键的部分,直接关系到脚本是否可以回放成功
从概念上,关联的主要作用是,去除前序调用返回结果中的某些动态值,传递给后续的调用
例如:客户端链接服务器,记录状态生成session id,服务端采用当前时间戳进行运算生成,然后进行编码,在回放时存在问题,因为此时的服务器有了新的session id,因为时间改变了,导致脚本回放失败。
解决方法就是,脚本回放过程中,实时抓取时间错和计算值,然后实时替换到后续中需要使用这两个值的地方,这个过程就是关联
LoadRunner提供了功能强大的关联函数web_reg_save_param(),这个关联函数支持多种动态值的获取方式,用的最多的是基于 '前序字符串匹配' 加上 '后续字符串匹配'的方式,其中字符串匹配,支持正则表达式
组要特别注意的是:web_reg_save_param()函数是注册型函数,必须放在获取动态值所属的请求前面,相当于先声明后调用
4,加入检查点
检查点,类似功能测试中的断言,但是性能测试脚本,不想功能测试脚本那样需要加入很多的断言,往往只在一些关键步骤加入很少量的检查点即可,这些检查点的主要作用是,保证脚本按照原本设计的路径执行
最常用的检查点函数是web_reg_find(),它的作用是通过指定左右边界的方式 '在页面查找相应的内容'
需要注意的是:web_reg_find()函数也是注册型函数,即放在所检查的页面之前,否则会检查失败
完成脚本开发后,按照个人经验,建议按照下列顺序执行:
1,以单用户的方式,在有思考时间的情况下执行脚本,确保脚本能够顺利执行,并且验证脚本行为以及执行结果是否正确;
2,以单用户的方式,在思考时间为零的情况下执行脚本,确保脚本能够顺利执行,并且验证脚本行为以及执行结果是否正确;
3,以并发用户的方式,在有思考时间的情况下执行脚本,确保脚本能够顺利执行,并且验证脚本行为以及执行结果是否正确;
4,以并发用户的方式,在思考时间为零的情况下执行脚本,确保脚本能够顺利执行,并且验证脚本行为以及执行结果是否正确
只有上述四个测试全部通过,虚拟用户脚本才算顺利完成
同一事务的响应时间变慢了
系统资源的占用率变高了
网络带宽的使用率变高了
需要注意的是:这些恶化趋势的前提是,完全相同的环境以及测试负载
假如:性能基准测试比较结果得知,用户登陆时间从2s变成4s
1,首先验证在单用户情况下,是否出现响应时间变长的问题。具体就是,将用户登陆的虚拟脚本单独拿出来,建立一个单用户运行的测试场景执行,观察单用户登陆响应时间是否变慢
2,如果变慢了,说明单用户登陆场景可以重现性能问题,处理方法是:分析单用户登陆的后端日志文件,查看完成登陆操作的时间都花在哪些步骤上,相比之前哪些步骤时间长了,或者多处哪些额外的步骤
3,如果没有问题,说明我们必须在有压力情况下重现这个性能问题。为此我们要基于用户登陆的虚拟用户脚本构建并发测试场景,因为并发量不确定,常用做法是,直接采用性能基准测试中的并发用户数和思考时间,如果无法重现,可以适当地逐步加大测试负载,并观察响应时间地变化趋势
4,需要注意地是:千万不要使用过大地测试负载,因为测试负载过的大,系统资源也会称为性能瓶颈,一定会使响应时间变长,这时,响应时间变长主要是资源瓶颈造成的,不是最初原因
如果此时可以重现问题,那就可以进一步去分析并发场景下,用户登陆擦偶作地时间切片,找到具体原因
如果此时还不能重现问题,情况就比较负责,可能是登陆操作与其他业务操作之间存在依赖,或者某种资源竞争关系
当定位到 '性能'恶化原因并修复后,我们还会再执行一轮性基准测试,确保对外发布地性能基准测试指标没有变坏
可以说,通过对每个预发布版本地性能基准测试,确保新发布系统的整体性能不会下降,这就是性能基准测试的最终目的
从性能测试设计角度看,需要注意三点:
1,性能基准测试中虚拟用户脚本的选择和配比,需要尽可能地匹配实际负载情况
2,总体负载设计不宜过高,通常被测系统各类占用率指标需要控制在30%以内,尽量避免由于资源瓶颈引入的操作延时
3,每次性能基准测试前,一般需要对系统资源以及网络资源做一轮快速的基准测试,以保证每侧被测环境的一致性,同时也要保证数据库的数据量在同一个级别上
一般是采用 '波浪式'的测试负载,如先逐渐加大测试负载,在高负载情况下持续10多个小时,然后再逐渐降低负载,这样就构成了一个波浪,整个稳定性测试将由很多个这样的波浪连续组成
系统资源的所有监控指标不存在 '不可逆转'的上升趋势
事务的响应时间不存在逐渐变慢的趋势
事务的错误率不超过1%
1,在虚拟用户脚本的录制过程中直接添加
2,在虚拟用户脚本中,通过添加lr_rendzvous()函数添加
可以使用性能基准测试中的虚拟用户脚本,以及各个业务操作脚本的百分比,压测单机部署的被测系统
采用人工的方式不断增加测试负载直到单机系统的吞吐量指标达到临界值,由此就可以直到单台机器的处理能力
理论上,整个集群的处理能力等于单台机器的处理能力乘以集群的机器数,但是实际的集群整体处理能力一定小于这个值,具体小多少就要靠实际的测试验证了
理想的状态是,整体集群的处理能力能够随着集群机器数量的增长呈线性增长,但是,随着机器数量的不断增长,总会在达到某个临界值后,集群整体处理能力不再继续呈现线性增长。这个临界值多少,也需要通过容量规划测试找出来
另外,容量规划测试的测试结果还可以被用作系统容量设计的依据。如,企业级产品的目标用户规模通常是可以预估的,那么我们可以通过这些预估的系统负载计算出软件部署的集群规模,并且可以在具体实施后通过容量测试的方法进行验证。