3、测试脚本开发:编写可复用的压测脚本,参数化与关联,断言与监听器配置

好,咱们进入实战环节。脚本开发这块,说白了就是把你脑子里的压测场景,翻译成工具能听懂的语言。我个人习惯把脚本开发分成三个层次:先能跑,再能复用,最后能自动验证。今天咱们就按这个路子来。

核心观点:一个优秀的压测脚本,不是写出来就完事了。它要能应对不同环境、不同数据、不同业务组合。我见过太多团队,每次压测都重写脚本,那效率太低了。

3.1 脚本结构设计:从单线程到可复用

先说说脚本的整体骨架。我一般会把脚本拆成三块:初始化块、业务块、清理块。

  • 初始化块:放全局变量、默认参数、连接配置。这部分只跑一次。
  • 业务块:真正的压测逻辑。登录、查询、下单、支付,按顺序放好。
  • 清理块:释放资源、关闭连接、清理测试数据。

为什么要这么分?你想想看,如果每次压测都要重新登录,那登录接口的压力会非常大,反而掩盖了真正要测的业务接口。我在项目中遇到过这种情况,一开始没注意,结果压测报告出来,登录接口的TPS比业务接口还高,领导一看就懵了。

嗯,这里要注意:初始化块和清理块不要放在事务控制器里。它们不计入压测结果。

3.2 参数化:让脚本活起来

参数化是脚本复用的基础。说白了,就是把硬编码的值变成变量。我常用的参数化方式有四种:

方式 适用场景 我的建议
CSV数据文件 大量用户数据、商品ID 最常用,注意文件编码
函数助手 随机数、时间戳、UUID 适合生成唯一标识
用户自定义变量 全局配置、环境切换 配合属性传递更灵活
数据库结果集 从数据库动态获取数据 性能开销大,慎用

举个例子,压测一个商品详情页。你不能让所有虚拟用户都看同一个商品吧?那样缓存一命中,结果就失真了。我一般会准备一个商品ID的CSV文件,里面放几千个真实商品ID,让每个用户随机取一个。

// CSV文件内容示例
// product_ids.csv
10001,10002,10003,10004,10005
// 在JMeter中配置CSV Data Set Config
// 变量名:productId
// 共享模式:所有线程

小技巧:CSV文件的行数最好大于虚拟用户数。如果不够,可以设置循环模式为「遇到EOF再次循环」。但要注意,这样可能会导致数据重复,影响结果准确性。

3.3 关联:把接口串起来

关联是压测脚本里最容易出问题的地方。为什么?因为很多新手不知道,接口之间是有依赖关系的。比如,你要下单,必须先拿到用户的token和商品的库存ID。

我常用的关联手段有两种:正则表达式提取器和JSON提取器。我个人更推荐JSON提取器,因为现在大部分接口返回的都是JSON格式,解析起来更直观。

// 假设登录接口返回如下JSON
{
  "code": 0,
  "data": {
    "token": "abc123xyz",
    "userId": 88888
  }
}

// JSON提取器配置
// 变量名:token
// JSON表达式:$.data.token
// 匹配编号:1

关联的坑在哪里?我曾经遇到过一个情况:登录接口返回的token有时效性,但脚本里没做token刷新逻辑。结果压测跑了半小时后,所有请求都返回401。嗯,这里要记住:关联的值一定要考虑有效期。如果token过期,脚本里要加一个判断,自动重新登录。

避坑指南:我曾经在压测一个支付流程时,关联了一个订单号。但订单号生成规则里包含了时间戳,导致每次请求的订单号都不一样。结果断言一直失败。后来发现,是关联的表达式写错了,匹配到了多个值。记住:关联一定要用「调试取样器」先验证一下提取的值对不对。

3.4 断言:让脚本自己会检查

断言是压测脚本的「质检员」。没有断言的压测,就像闭着眼睛开车——你以为跑得挺快,其实早就跑偏了。

我常用的断言类型:

  • 响应断言:检查返回的状态码、响应文本。最基础,但够用。
  • JSON断言:检查JSON里的某个字段值。适合接口返回结构固定的场景。
  • 大小断言:检查响应数据的大小。适合判断是否返回了完整数据。
  • 持续时间断言:检查响应时间是否超过阈值。这个我特别喜欢用,能直接发现慢接口。

举个例子,压测一个查询接口。正常返回的数据里,data.list 应该是一个数组,长度大于0。如果返回空数组,说明查询条件有问题。这时候用JSON断言检查 $.data.list.length 是否大于0,就能快速发现问题。

// JSON断言配置示例
// 断言字段:$.code
// 预期值:0
// 类型:等于

// 再加一个断言
// 断言字段:$.data.list.length
// 预期值:1
// 类型:大于

我的习惯:每个关键接口至少加两个断言。一个检查业务状态码,一个检查关键数据字段。这样既能发现接口挂了,也能发现接口返回了错误数据。

3.5 监听器配置:别让数据白跑

监听器是压测的「仪表盘」。没有监听器,你跑完压测都不知道结果怎么样。但监听器也不能乱加,加多了会影响压测本身的性能。

我一般这样配置:

  1. 压测过程中:只开一个「聚合报告」和一个「图形结果」。够用,不占资源。
  2. 调试阶段:开「查看结果树」和「调试取样器」。方便定位问题。
  3. 压测结束后:用「简单数据写入器」把结果存成CSV文件。方便后续分析。

这里有个误区:很多人喜欢在压测时开着「查看结果树」。你想想看,每个请求的响应数据都要存到内存里,还要渲染到界面上,这得消耗多少资源?我见过一个团队,压测1000并发,结果「查看结果树」直接撑爆了内存。

注意:监听器的配置要跟压测场景匹配。如果是长时间压测(比如8小时稳定性测试),建议只保留「简单数据写入器」,其他监听器全部关掉。等压测结束后,再用工具分析CSV文件。

3.6 实战案例:一个完整的压测脚本

说了这么多,咱们来个完整的例子。假设要压测一个电商的「搜索-详情-加购-下单」流程。

// 脚本结构
// 1. 初始化块(只跑一次)
//    - 设置全局变量:baseUrl、env
//    - 读取CSV文件:用户数据、商品数据

// 2. 业务块(循环执行)
//    - 登录(关联token)
//    - 搜索商品(参数化关键词)
//    - 查看商品详情(关联商品ID)
//    - 加入购物车(参数化数量)
//    - 提交订单(关联订单号)
//    - 支付(断言检查支付状态)

// 3. 清理块(只跑一次)
//    - 退出登录
//    - 清理测试数据

这个脚本里,参数化用到了CSV文件(用户数据、商品关键词),关联用到了JSON提取器(token、商品ID、订单号),断言用到了响应断言和JSON断言。监听器只开了聚合报告和简单数据写入器。

嗯,这里有个细节:每个接口之间要加一个「思考时间」。我用的是「固定定时器」,设置300-500毫秒。为什么?因为真实用户不会连续点击,中间会有停顿。不加思考时间,压测出来的TPS会虚高,跟线上表现对不上。

总结一下:脚本开发的核心就四个字——可复用、可验证。参数化让脚本能应对不同数据,关联让脚本能串联业务,断言让脚本能自我检查,监听器让结果能落地分析。把这四点做好,你的压测脚本就能从「一次性工具」变成「可复用的资产」。

压测脚本开发核心逻辑 初始化块 全局变量 CSV数据加载 连接配置 业务块 参数化请求 关联提取 断言验证 清理块 释放资源 关闭连接 数据清理 参数化 CSV / 函数助手 用户自定义变量 关联 正则提取器 JSON提取器 断言 响应 / JSON 大小 / 持续时间 监听器 聚合报告 数据写入器 核心目标:可复用 + 可验证 参数化 → 应对不同数据 | 关联 → 串联业务 | 断言 → 自我检查 | 监听器 → 结果落地 从「一次性工具」变成「可复用的资产」

好了,脚本开发这块就聊到这儿。记住:好的脚本是改出来的,不是写出来的。第一次跑通只是开始,后面要根据压测结果不断优化参数化策略、调整断言阈值、精简监听器配置。这才是压测脚本开发的常态。

想要更多资料,联系可可