软件测试之——性能测试

性能测试的定义

性能测试的定义:通过自动化测试工具或者代码手段,来模拟正常、峰值负载访问被测系统,来观测系统各项性能指标是否合格的过程。

软件测试之——性能测试_第1张图片

性能测试的分类

  1. 基于代码的性能测试(关注点是函数或方法执行的效率)
  2. 基于协议的性能测试(关注服务器的性能)
  1. 客户端的性能测试(页面或者客户端的响应时间)

服务端测试的分类

  • 压力测试:在一定的软硬件、网络条件下,模拟用户高并发(峰值负载),持续一段时间,检测系统的各项性能指标,关注峰值下的系统的性能表现(秒杀、团购、抢票)
    • 目的:监测被测系统在峰值下的运行情况,给最坏情况(系统崩溃)设计预案
    • 场景模型:门型场景,大量线程同时开始,经过一段时间后,又同时结束
  • 负载测试:在一定的软硬件、网络条件下,通过改变负载的方式,监测系统的各项性能指标,得到系统在正常工作情况下,系统的最大用户数、最佳用户数,定位系统的瓶颈
    • 场景模型:拱门场景。线程不同时开始,经过一段时间后,陆续结束线程
    • 软件测试之——性能测试_第2张图片

  • 配置测试:改变软硬件配置(架构配置、参数配置),观测不同配置条件下的性能状态
  • 基准测试:在一定的软硬件、网络条件下,模拟单用户操作系统,检测系统各项性能指标。为后面深入的性能测试做一个数据对比。
  • 并发测试:测试同一模块、同一应用在高并发的情况下,接口工作是否正常。目的是主要检查应用或者接口在多用户情况下,是否存在缺陷(比如死锁等)
  • 容量测试:在一定的软硬件、网络条件下,改变数据库的容量,模拟多用户,监测各项性能指标的过程。寻找数据容量的极限值
  • 稳定性测试:主要强调长时间、正常负载情况下,观测系统各项指标的稳定性,不会出现致命的问题。7*24小时。8小时、24小时、48小时。目的是检测系统长时间运行,系统的稳定性、是否有异常表现(宕机、出现致命问题等)

性能测试使用

  • 上新系统:用户场景(大量用户、同时使用、某个时间段内使用)适合用基准测试、负载测试、压力测试、容量测试
  • 扩容:分析了历史系统自身的性能标新,适当的扩容。基准测试、负载测试、压力测试、容量测试
  • 调优:针对以上线的系统越来越慢,对系统进行优化配置,提升性能表现。基准测试、配置测试
  • 修复:解决线上系统的并发死锁、内存泄漏等问题。并发测试
  • 秒杀、团购:基准测试、负载测试、压力测试

性能测试的介入时机,一般是在功能、接口测试都已经完成之后再来做性能测试。

性能测试的指标

  • 响应时间:用户发出请求到服务器处理完成请求返回给客户端的这段时间
  • 吞吐量:衡量系统的业务处理能力。TPS:每秒事务数。QPS:每秒请求数
  • 资源利用率:cpu、内存、网络、磁盘读写io。一般资源的利用率不高于70%-80%,如果某项高于这个值,则可能是性能瓶颈
  • 错误率:系统在负载情况下,失败请求的概率。错误率=(失败请求数/总请求数)*100。和功能测试的错误相区别,在性能测试中,所谓的错误一般是指由系统超时引起的错误,而不是指功能错误。不同的系统错误容错率不同。普通的业务系统,错误率不超过万分之一就可以了,有的大型系统,亿分之一。

常用专业术语

  • 集合点:大量进程统一开始的地方
  • 关联
  • 检查点:断言
  • 用户数:在线用户数,并发用户数,系统用户数
  • PV:页面访问量。客户端向服务器请求的数量,通常是作为网站系统的处理能力的衡量标准
  • UV:独立用户访问量,根据用户数量来进行统计,访问系统一次算一个UV

性能测试流程

  • 性能测试需求分析
    • 弄清楚本次性能测试的需求,性能测试的目的是什么,明确后续性能的要点
    • 主要需求有几种:新系统的能力验证、历史系统(明确的客户需求)、找出系统的性能瓶颈、稳定性验证(强度测试)
  • 了解系统架构
    • 在环境搭建阶段,了解项目的部署
    • 在性能测试分析阶段,要通过不同的系统架构去设计相应的测试模型(真实模拟用户实际操作场景)
    • 在性能测试定位和调优阶段,更要深入这些技术细节才能发现具体问题的位置
  • 分析性能测试点(场景设计)
    • 场景选择有哪些原则
      • 使用频率高的业务
      • 关键程度非常高的业务
      • 资源占用非常严重的业务
  • 测试工具选型
    • 开源工具
    • 商业工具
    • 自研工具
  • 测试计划
    • 简介
    • 性能测试的需求
    • 测试环境
    • 数据准备
    • 测试工具
    • 测试策略
    • 人力和时间安排
  • 测试环境搭建
    • 主要保证测试环境与生产环境一致
      • 硬件环境(服务器、网络)机器数与请求数按比例一致
      • 软件环境(系统版本、软件版本)
      • 使用场景的一致性
  • 测试执行
    • 准备测试数据
    • 使用测试工具实现测试操作
    • 根据测试策略,使用不同的虚拟用户和测试组合来进行测试
    • 监控系统资源利用率
    • 重复3,4步,直到找到性能问题
  • 瓶颈定位及性能调优
    • 调优需要开发、运维工程师参与和主导
    • 反复验证性能是否有提升
    • 性能调优的顺序,从易到难
      • 硬件问题
      • 网络问题
      • 应用服务器、数据库的配置问题
      • 源码、数据库脚本问题
      • 系统架构问题

jmeter

目录结构

  • bin 目录:存放可执行文件和配置文件
    • jmeter.bat:Windows的启动文件
    • jmeter.log:日志文件
    • jmeter.sh:Linux的启动文件
    • jmeter.properties:系统配置文件
    • jmeter-server.bat:Windows分布式测试要用到的服务器配置
    • jmeter-serve:linux分布式测试要用到的服务器配置
  • docs和printable_docs目录:存放api的帮助文档
  • lib目录:存放jmeter所依赖的jar包和用户扩展所依赖的jar包

常用设置

  • 修改语言:jmeter.properties文件中添加:language=zh_CN
  • 修改编码:jmeter.properties文件中添加:sampleresult.default.encoding=UTF-8

基本使用流程

  1. 启动jmeter
  2. 在“测试计划”下添加“线程组”
  1. 在“线程组”在添加“HTTP请求”取样器
  2. 填写“HTTP请求”的相关请求数据
  1. 在“线程组”下添加‘察看结果树’监听器
  2. 点击“启动”按钮运行,并查看结果

常用元件介绍

  • 线程组:用户模拟多线程,一个线程代表一个用户的操作
  • 配置元件:进行测试环境和测试数据的初始化,类似于自动化脚本中的setup
  • 前置处理器:对要发送的请求进行预处理,类似于自动化脚本中的参数化
  • 取样器:往服务器发送请求,类似于自动化脚本中的发送请求
  • 后置处理器:对收到的服务器的响应数据进行处理,类似于自动化叫嗯中获取响应中特定字段的操作
  • 断言:将收到的响应结果与预期结果做对比
  • 监听器:查看测试脚本运行的结果和日志,类似于自动化测试脚本中的测试报告
  • 定时器:等待一段时间,类似于自行化测试脚本中的sleep
  • 测试片段:封装基本功能的代码块,不单独执行,需要脚本进行调用,类似于自动化中封装的函数

元件作用域

  1. 在jmeter中,元件的作用域是根据测试计划的树形结构中元件的父子关系来确定的
  2. 元件中取样器是核心,其他组件都是以取样器为核心运行的,组件添加的位置不同,生成的取样器也不同
  1. 取样器:取样器都是一个独立的请求,不合其他元件相互作用,因此不存在作用域的问题
  2. 逻辑控制器:该元件只对其子节点的取样器和逻辑控制器起作用
  1. 其他六大元件:除取样器和逻辑控制符外,如果是某个取样器的子节点,则该元件对其父子节点起作用;如果其父节点不是取样器,则其作用域是该元件父节点下的其他所有后代节点(包括子节点,子节点的子节点等)

元件的执行顺序

  1. 配置元件
  2. 前置处理器
  1. 定时器
  2. 取样器
  1. 后置处理器
  2. 断言
  1. 监听器

注意:

  • jmeter元件执行顺序和自动化脚本执行顺序差不多
  • 前置处理器,后置处理器,断言等元件功能只对取样器起作用,如果在它们的作用域内没有取样器,则不会执行
  • 如果在同一作用域范围内有多个同一类型的元件,则这些元件按照它们在测试计划中的上下顺序依次执行

组件

重点组件有:

  1. 线程组
  2. HTTP取样器
  1. 查看结果树
  2. Cookie管理器

线程组

线程组是控制用于执行测试的线程数,也可以把一个线程理解为一个测试用户,线程组即一组用户。

线程组的特点:

  • 设定线程数(模拟多人操作)
  • 取样器(请求)和逻辑控制器必须依赖线程组才能使用
  • 线程组可以添加多个,多个线程组可以并行和串行,默认是并行。设置串行的方式:“测试计划”的设置里面,勾选独立运行每个线程组
  • 线程组下可以添加其他元件下的组件

线程组的分类

  • 线程组
  • setUp线程组:最先执行
  • tearDown线程组:最后执行

线程组属性设置

  • 取样器错误后要执行的动作
    • 继续:如果取样器中执行出现错误失败的时候,请求不会停止,继续执行。一般选择此项
    • 启动下一进程循环:如果出错,则同一线程中的余下请求将不再执行,直接开始新一轮迭代
    • 停止线程:只限当前线程停止,不影响其他线程执行,一般不会设置此项
    • 停止测试:当前执行的线程全部执行完毕后结束
    • 立即停止测试:立刻停止所有线程操作
  • Ramp-Up时间(秒):这些线程总共需要多少时间启动完成
  • 循环次数:
    • 可以设置次数;
    • 也可以选择永远,选择永远时,要配合调度器使用
      • 勾选调度器,设置持续时间(想要运行多久,如60*60*24表示持续24小时)
      • s设置启动延迟(延迟多少秒后起送线程)
  • same user on each iteration: 每次迭代使用相同的线程,节省创建新线程的资源。一般会结合cookie管理中的 use Threadgroup configuration to control cookie cearing使用,避免每次迭代都使用相同的cookie信息

http请求

属性配置

  • 名称:自定义
  • 注释:自定义
  • 协议:默认是http
  • 服务器名称或ip:只填域名或ip
  • 端口:默认是80
  • 方法:get/post……
  • 路径:资源路径
  • 内容编码:请求的编码格式,如:utf-8
  • 对post使用multipart/form-data:需要上传文件时候勾选
  • 与浏览器兼容的头:对于只能浏览器请求的网站,可以勾选这个
  • 参数:以key-value形式的传参的
  • 消息体数据:利用json的形式来传参的,写在这里面
  • 文件上传:文件删除上传的时候利用这个

请求默认值设置

“添加”-》“配置元件”-》“HTTP请求默认值”这个路径中设置,请求的协议、域名或ip、端口号。

这样其他请求就可以使用这个默认配置,而不用再配置协议、域名或ip、端口号了

发送get请求

直接在路径中带参数

软件测试之——性能测试_第3张图片

以key-value的形式传参数

软件测试之——性能测试_第4张图片

发送post请求

以键值对形式传参

直接在“参数”的下面添加参数,适合于content-type为application/x-www-form-urlencoded的时候,不需要单独设置请求头。

以json的形式传参

  1. 在“http请求”页面中-》“消息体数据”中添加参数的json字符串"
  2. 必须为该http请求添加一个“配置元件”-》“HTTP信息头管理器”,并且在该页面设置:conten-type为application/json

传文件

只传文件的情况:

  1. 选中“对post会用multipart/form-data”
  2. 在文件上传中设置
    1. 文件名称:即文件的全路径
    2. 参数名称
    1. MIME类型:multipart/form-data

除了文件,还要传其他普通参数的情况:

  1. 选中“对post会用multipart/form-data”
  2. 在文件上传中设置
    1. 文件名称:即文件的全路径
    2. 参数名称
    1. MIME类型:multipart/form-data
  1. 在“参数”中设置普通参数

察看结果树

会显示“查看结果树”作用域中的所有http请求。可以查看请求的结果

cookie管理器

cookie管理器专门用于管理客户端的cookie信息,一般用于需要登录的场景保持与服务器端的会话。如果不设置该管理器,则无法再jmeter中保持会话

添加方式:“配置元件”-》“cookie管理器”

cookie管理器一般不需要专门设置,添加了就可以了

工具自带的录制脚本

  1. 在测试计划下,“添加”-》“非测试元件”-》“HTTP代理服务器”
  2. 设置监听的端口
  1. “Test Plan creation”-》目标控制器下拉列表,选择一个目录,表示录制的脚本存放在jmeter的位置
  2. “request filtering”-》“排除模式”-》“添加” 排除css,jspng等
  1. 电脑打开代理设置,ip为本机ip,端口为第2步设置的端口
  2. 这样jmeter就能录制到,点击运行的页面上的请求接口了,并将http请求存放到第3步的位置

jmeter参数化

每次请求发送不同的值,就需要用到参数化。

用户定义的变量

添加方式:“测试计划”-》“线程组”-》添加“配置元件”-》“用户定义的变量”

步骤:

  1. 添加线程组
  2. 添加用户定义的变量(通过配置元件或直接在测试计划属性内添加)
  1. 添加http请求
  2. 添加查看结果树

优势:所有要用到该值的订单,统一使用一个变量${变量名},便于维护

劣势:多个用户也只能取一个值,无法让多个用户使用多个值

CSV文件参数化

添加方式:“测试计划”-》“线程组”-》添加“配置元件”-》“CSV数据文件设置”

步骤:

  1. 定义csv文件,各个字段之间以逗号分隔。
  2. 添加线程组
  1. 添加CSV数据文件设置
    1. 选择CSV文件路径
    2. 设置文件编码
    1. 指定变量名称,以逗号分隔: username,passeord
    2. 忽略首行:如果首行不是测试数据,是字段名,这里选true,表示不读取首行
    1. 是否允许带引号:
    2. 遇到文件结束符再次循环: 文件中的数据条数读完时,线程数还没运行完,是否需要再去从头开始读取文件中的数据
    1. 遇到文件结束符停止线程:如果文件结束时,还有未运行完的线程,是否要停止线程
  1. 添加http请求
  2. 添加查看结果树

优势:对同一个用户多次循环,可以取不同的值,适合数据量比较大的参数化测试,是在接口测试或性能测试中常用的一种方式。

jmeter断言

Xpath断言

主要用于HTML格式的响应断言。

添加方式:“测试计划”-》“线程组”-》“HTTP请求”-》右键“添加断言”-》“xpath”断言

  • 勾选Use Tidy(tolerant parser),使其兼容
  • 文本框中写xpath表达式。
    • 如果有多个条件,用and连接
    • 要获取元素的文本,用text()
    • 要获取任意属性的值用attribute::属性名表示

软件测试之——性能测试_第5张图片

JSON断言

主要用于json格式的响应断言,断言非json格式会失败

添加方式:测试计划-》线程组-》http请求-》右键添加断言-》json断言

步骤:

  1. 首先解析json数据,如果数据不是json,则验证失败
  2. 使用json语法搜索指定的路径。如果目标找不到就会失败
  1. 如果在文档中找到json路径,并且要求对期望值进行验证,那么它将执行验证操作

“Assert JSON Path exists”:设置json的路径,必须用$.表示json的根目录。如:$.code,表示取code的值

“Additionally assert value”: 勾选后可以填写预期结果

持续时间断言

主要用于断言请求的响应时间是否在设定的时间范围内。

添加方式:测试计划-》线程组-》HTTP请求-》右键添加断言-》断言持续时间

步骤:

  1. 添加线程组
  2. 添加HTTP请求
  1. 添加持续时间断言
    1. Main sample only表示主线程
    2. 持续时间设置
  1. 添加查看结果树

jmeter关联

关联主要用于解决性能测试中多个接口之间的依赖关系,一般可以通过后置处理器来提取。

常用的关联方法:

  • 正则表达式提取器
  • XPath提取器
  • JSON提取器

正则表达式关联

添加方式:测试计划-》线程组-》HTTP请求-》右键添加后置处理器-》正则表达式提取器

步骤:

  1. 添加线程组
  2. 添加HTTP请求
  1. 添加正则表达式提取器,
    1. 设置引用名称(要保存的变量名称)
    2. 设置正则表达式
    1. 模板:
      1. $1$ 表示1个值, $2$ 表示去2个值,正则表达式中有n个小括号,这里就写$n$
      2. 如果n>1,还需要添加:线程组-》取样器-》Debug Sample(调试取样器)。这个调试取样器不做任何配置,添加就行
      1. 以上设置过后,运行该接口后,查看调试取样器,取得对应的变量名(a步骤设置的名称只是一个统一名称,当有多个值是,一般会在设置的名称后加下标数据,这样才能取到一个真正的变量名)
    1. 匹配数字:表示取第几个值。0表示随机取一个,-1表示所有值都取
    2. 缺省值:正则表达式没有匹配时的值
  1. 添加HTTP请求
  2. 添加查看结果树

XPath关联

添加方式:测试计划-》线程组-》HTTP请求-》右键添加后置处理器-》xpath提取器

步骤:

  1. 添加线程组
  2. 添加HTTP请求
  1. 添加XPATH提取器
  2. 添加debug sampler
  1. 添加HTTP请求
  2. 添加查看结果树

JSON关联

添加方式:测试计划-》线程组-》HTTP请求-》右键添加后置处理器-》json提取器

步骤:

  1. 添加线程组
  2. 添加HTTP请求
  1. 添加json提取器
  2. 添加取样器-》debug sampler
  1. 添加HTTP请求
  2. 添加查看结果树

beanshell应用

beanshell是一个小型,免费,可嵌入的java源代码解释器,具有用java编写的对象脚本功能。

常见的beanshell组件:

  • BeanShell Timer 定时器
  • BeanShell PreProcessor 前置处理器
  • BeanShell Sample 采样器
  • BeanShell PostProcessor 后置处理器
  • BeanShell Assertion 断言
  • BeanShell Listener 监听器

添加方式:测试计划-》线程组-》HTTP请求-》右键添加前置处理器-》BeanShell processor

在文本框中添加sign获取的shell

import org.apache.commons.code.digest.DigestUtils;

String sign='要签名的字符串';
String sign_md5 = DigestUtils.md5Hex(sign);
// 将签名放入变量signStr中
vars.put("signStr",sign_md5);

jmeter连接mysql

  • 下载mysql连接驱动包
  • 下载完成后,将mysql驱动防止到jmeter安装路径的lib目录下
  • 重启jmeter
  • 在测试计划内添加mysql驱动
  • 在线程组内添加-》配置元件-》JDBC Connection Configuration,并配置连接属性
    • 配置variable name for created pool,作为配置的这个数据库的标识变量
    • 配置database connection
  • 添加线程组-》取样器-》JDBC request
  • 软件测试之——性能测试_第6张图片

jmeter控制器

  • if 控制器:用来控制它下面的测试元素是否运行。
    • 添加方式:测试计划-》线程组-》右键添加逻辑控制器--》如果(if)控制器
    • 在条件框中输入条件
    • 或者“interpret condition as variable expression”打钩
      • Tools-》函数助手对话框-》选择要用的函数-》将条件框中输入的条件,复制到这边-》生成对应函数的条件表达式-》将获得的表达式覆盖到条件框中
  • 事务控制器:jmeter默认把每一个请求都统计成了一个事务,但有时候我们根据业务需求,会把多个操作统计成一个事务。
    • 添加方式:测试计划-》线程组-》右键添加逻辑控制器--》事务控制器
    • generate parent sample 勾选之后,生成“聚合报告”的时候,就是作为一个整体,而不是显示事务中的每一项内容
    • include duration of timer and pre-post processors in generated sample。是否包含计时器、前后置处理器的运行时间,一般不勾选

同步定时器(集合点)

添加方式:测试计划--》线程组--》HTTP请求--》右键添加定时器--》Synchronizing Timer

同步定时器目的是阻塞线程,直到阻塞了n个线程,然后立即释放它们。用来做大数据量的并发请求

步骤:

  1. 添加线程组,设置线程数=100,Ramp-up时间=10s
  2. 添加http请求
  1. 添加同步定时器
    1. 设置模拟用户组的数量,
    2. 超时时间设置,不设置,会一直等到数量到达a步骤设置的时候,才执行。设置时间的话,时间一到,还未达到a步骤设置的时间,也会执行。一般情况下,超时时间设置不能短于a步骤设置的线程数量生成的总时间,否则,模拟用户组的数量就达不到它本身设置的线程数的效果
  1. 添加查看结果树
  2. 添加监听器-聚合报告

常量吞吐量定时器

可以让jmeter以指定数字的吞吐量(以每分钟的样本数为单位,而不是每秒)执行,通常用于负载测试、压力测试等。吞吐量计算的范围可以指定为当前线程、当前线程组、所有线程组

添加方式:测试计划-》线程组-》HTTP请求-》右键添加定时器-》constant throughput timer

步骤:

  1. 添加线程组,循环次数设置成永远
  2. 添加HTTP请求
  1. 添加常用吞吐定时器,设置每分钟目标吞吐量
  2. 添加查看结果树
  1. 添加监听器-聚合报告,查看吞吐量

jmeter分布式测试

在使用jmeter进行性能测试时,如果并发数比较大,单台电脑的CPU和内存可能无法支持,这时,就可以使用jmeter提供的分布式测试的功能。

软件测试之——性能测试_第7张图片

注意事项:

  1. 防火墙必须关闭
  2. 所有的测试机必须在同一个子网下,能互相ping通
  1. 确保jmeter能够访问服务器
  2. 确保测试机上的jdk和jmeter是同一版本
  1. 禁用jmeter的RMI SSL配置项

代理机(slave)配置:

  1. agent上必须安装jmeter和jdk,不管是Linux 还是Windows
  2. 如果在同一台机器上跑多台代理机,必须要修改jmeter设置中的server_port.如果多台不同的电脑上跑代理则不需要修改。如果代理机是虚拟机,必须保证虚拟机和主机之间相互都能ping通,否则无法正常测试
  1. 修改RMI SSL disable 为true
  2. 通过agent上的jmeter-server.bat文件启动代理机(如果提示没有权限,则需要先将jmeter目录权限改为777)

注意:linux上通过命令+参数启动:

./jmeter-server -Djava.rmi.server.host.name=ip地址

主控机(master)配置

  1. master的jmeter的bin目录下的jmeter.properties配置文件,修改“remote_hosts”为代理机ip地址和端口
    1. 如:remote_host=127.0.0.1:2099,192.168.2.200:1099
  1. 修改RMI SSL disable为true
  2. 启动jmeter
  1. 选择菜单:运行-》远程启动/远程启动所有

注意:如果通过远程执行无法显示响应内容的话,需要将jmeter.properties中的mode=Standard取消注释

jmeter命令行方式生成测试报告

生成jmeter报告,先配置jmeter环境变量:

  1. JMETER_HOME:jmeter路径
  2. Path里面加上%JMETER_HOME%\bin

生成报告的命令:

jmeter -n -t xxx.jmx -l http.jtl -e -o report
  • -n:以非GUI形式运行jmeter
  • -t:jmx脚本路径
  • -l:运行结果保存路径(.jtl),此文件必须不存在,路径+文件名
  • -e:在脚本运行结束后生成HTML报告
  • -o:用于存放html报告的目录,只能是一个空目录

如果已经有之前生成的jtl文件,也可以直接使用jtl文件生成报告

命令如下:

jmeter -g xxx.jtl -o report

服务器资源监控

jmeter安装的机器上:

  1. 下载jmeter扩展插件,并放到jmeter安装路径的lib/ext目录下,重启jmeter即可。下载地址:https://jmeter-plugins.org/get/
  2. 打开jmeter的“选项”-》“plugin manager”,选择avaliable plugin,搜索perf,选择perfmon,安装重启jmeter即可
  1. 在测试脚本中增加对应监听器:jp@gc - PerfMon Metrics Colletor
    1. 设置监听的服务器的ip和端口4444,以及监听的资源CPU、内存、io等

被测服务器上设置

  1. 下载server-agent,https://github.com/undera/perfmon-agent/blob/master/README.md
  2. 上传server-agent到服务器
  1. 启动server-agent :./startAgent.sh

如果对python自动化测试、web自动化、接口自动化、移动端自动化、大型互联网架构技术、面试经验交流等等感兴趣的老铁们,可以关注我。我会在公众号(程序员阿沐)/群里(810119819)不定期的发放免费的资料链接,这些资料都是从各个技术网站搜集、整理出来的,如果你有好的学习资料可以私聊发我,我会注明出处之后分享给大家。欢迎分享,欢迎评论,欢迎转发。需要资料的同学可以关注我获取资料链接。

你可能感兴趣的:(测试工具,压力测试)