第五章. 断言与逻辑控制:让脚本有脑子
第五章. 断言与逻辑控制:让脚本有脑子
Prorise第五章. 断言与逻辑控制:让脚本有 “脑子”
摘要:本章将解决 JMeter “盲目乐观” 的问题。默认情况下,只要服务器返回 HTTP 200,JMeter 就会判定测试通过,忽略了业务逻辑报错(如 “库存不足”)。我们将学习如何使用 断言 识别真正的业务失败,并利用 逻辑控制器 让脚本根据上一步的结果智能决定下一步的走向。
本章学习路径
我们将按照以下步骤打造智能脚本:
- 5.1 揭穿 “假成功” 现象
- 5.1.1 构造一个 “HTTP 200 但业务失败” 的接口
- 5.1.2 观察 JMeter 的误判
- 5.2 响应断言 (Response Assertion)
- 5.2.1 校验核心业务字段
- 5.2.2 设定自定义的失败消息
- 5.3 JSON 断言 (JSON Assertion)
- 5.3.1 精准校验结构化数据
- 5.3.2 验证数组长度与特定值
- 5.4 逻辑控制器 (If Controller)
- 5.4.1 场景:登录失败就不下单
- 5.4.2 JEXL3 表达式语法实战
5.1. 揭穿 “假成功” 现象
在上一章,我们完成了关联。但在实际开发中,接口返回 HTTP 200 并不代表业务成功。例如支付接口返回 {"code": 5001, "msg": "余额不足"},HTTP 状态码依然是 200。如果不加判断,JMeter 会认为这次请求是成功的,导致最终的压测报告显示 “100% 成功率”,这不仅误导,甚至可能掩盖严重的线上 Bug。
5.1.1. 改造靶场:模拟业务异常
我们需要修改 Spring Boot 代码,增加一个模拟库存扣减的接口,它会随机返回成功或失败。
文件路径:src/main/java/com/demo/jmeterdemo/controller/OrderController.java
请新建 OrderController 类:
1 | package com.demo.jmeterdemo.controller; |
重启项目,我们准备开始测试。
5.1.2. 观察 JMeter 的误判
在 JMeter 中新建线程组 " S02_断言测试 "。
添加 HTTP 请求,命名为 " API_下单 "。
配置如下参数:
- Path:
/api/order/create - Method:
POST
设置线程组 循环次数 为
10。运行并观察 察看结果树。
结果分析:你会发现 10 次请求全部都是 绿色盾牌。点开响应数据,你会发现其中夹杂着 {"code": 5001, "msg": "Out of Stock"}。
这就是 “假成功”。在真正的压测报告中,我们必须把这 30% 的库存不足标记为 “失败”,否则我们就不知道系统在什么并发量下会开始出现业务瓶颈。
5.2. 响应断言:最通用的门神
为了纠正 JMeter 的判断,我们需要添加 断言 (Assertion)。断言就是我们设定的 “通过标准”。
5.2.1. 添加响应断言
操作步骤:
- 右键点击 " API_下单 " -> 添加 -> 断言 -> 响应断言 (Response Assertion)。
- 配置以下参数:
| 参数项 | 配置值 | 解释 |
|---|---|---|
| 测试字段 (Apply to) | Main sample only | 只检查主请求。 |
| 测试字段 (Field to Test) | 响应文本 (Text Response) | 检查 Response Body 的内容。 |
| 模式匹配规则 | 包括 (Contains) | 只要包含指定字符串就算通过。 |
| 测试模式 (Patterns to Test) | "code": 200 | 点击【添加】按钮输入。这里我们强制要求返回结果必须包含这段 JSON 文本。 |
| 自定义失败消息 | 业务代码非 200 | 如果断言失败,结果树中会显示这句话,方便排查。 |
5.2.2. 验证效果
再次运行测试。
预期结果:在 察看结果树 中,你应该会看到大约 30% 的请求变成了 红色感叹号。点击红色的请求,展开 断言结果 (Assertion Failure Message),你会看到:Assertion error: false that ... contains "code": 200
这样,JMeter 的聚合报告中的 “Error %” 就能真实反映业务成功率了。
5.3. JSON 断言:结构化数据的专家
虽然 “响应断言” 简单好用,但通过字符串匹配 "code": 200 并不严谨。如果返回的 msg 里包含 code: 200 字符,可能会导致误判。
对于 JSON 接口,更推荐使用 JSON 断言。
5.3.1. 配置 JSON 断言
我们先禁用掉刚才的 “响应断言”(右键 -> 禁用),添加一个新的断言。
操作步骤:
- 右键点击 " API_下单 " -> 添加 -> 断言 -> JSON 断言 (JSON Assertion)。
- 配置参数:
| 参数项 | 配置值 | 解释 |
|---|---|---|
| Assert JSON Path exists | $.orderId | 我们要求返回结果中必须包含 orderId 字段。只有下单成功才有这个字段。 |
| Expected Value (可选) | (空) | 如果勾选了 Additionally assert value,可以校验字段的值。这里我们只校验 “是否存在”。 |
原理:当返回 {"code": 5001, "msg": "Out of Stock"} 时,JSON 中没有 orderId 字段,断言通过 JSON Path 找不到路径,判定为失败。
5.4. 逻辑控制器:让脚本学会 “止损”
默认情况下,JMeter 像一个只会按顺序执行命令的机器人:无论上一步是成功还是炸了,它都会坚定地执行下一步。但在真实的业务场景中,如果用户连 “登录” 都失败了,后续的 “下单”、“支付” 操作根本就不应该发生。继续执行这些无效请求,不仅浪费压测机的 CPU,还会让服务端产生大量无意义的 401 错误日志,干扰问题排查。
我们需要利用 If 控制器 (If Controller) 来实现逻辑判断:只有当条件满足时,才执行内部的组件。
5.4.1. 场景重构:依赖链路
为了演示这个功能,我们需要构建一个典型的依赖场景:
- 前置动作:用户尝试登录。
- 判断依据:提取登录接口返回的状态码
code。 - 分支逻辑:
- 如果
code == 200:执行 “API_下单”。 - 如果
code != 200:直接跳过,不做任何操作。
- 如果
准备工作:请确保你的 “API_登录” 请求下已经挂载了 JSON 提取器,并将状态码提取为变量 login_code。
5.4.2. 借助函数助手生成表达式
在配置 If 控制器之前,我们先解决最难的一步:如何写出正确的判断表达式?
手动编写 ${__jexl3(...)} 既容易错又难记。我们要利用 函数助手 自动生成代码。
操作步骤:
点击 JMeter 顶部菜单栏的 工具 (Tools) -> 函数助手对话框 (Function Helper Dialog)。
在左侧列表中找到并选中
__jexl3(这是 JMeter 高性能运算函数)。在右侧的 参数值 栏位中,输入你的逻辑表达式:
"${login_code}" == "200"点击底部的 生成 (Generate) 按钮。
复制 生成的字符串:
${__jexl3("${login_code}" == "200",)}。
语法细节:为什么变量 ${login_code} 外面要加双引号?这是为了防止空指针。如果提取失败,变量为空,表达式会变成 "" == "200"(合法);如果不加引号,会变成 == "200"(语法错误)。
5.4.3. 配置 If 控制器
拿到生成的代码后,配置控制器就非常简单了。
操作步骤:
- 右键点击 线程组 -> 添加 -> 逻辑控制器 -> 如果 (If) 控制器。
- 将 “API_下单” 请求 拖拽 到 “If 控制器” 的内部(使其成为子节点)。
- 在 If 控制器的面板中进行粘贴:
- Expression:粘贴刚才复制的代码
${__jexl3("${login_code}" == "200",)}。 - Interpret Condition as Variable Expression?:必须勾选。
- Expression:粘贴刚才复制的代码
始终勾选 “Interpret Condition as Variable Expression?”。这告诉 JMeter 直接使用高性能的 JEXL3 引擎处理变量,而不是启动笨重的 JavaScript 引擎。在高并发压测下,这一项配置能提升 10 倍以上的性能。
5.4.4. 验证 “止损” 效果
配置完成后,我们进行正反两面的测试,验证逻辑是否生效。
测试 A:正向用例(登录成功)
- 修改登录接口参数为正确的账号密码(
admin/123456)。 - 运行脚本。
- 观察:
login_code变为 200,你会在结果树中同时看到 “API_登录” 和 “API_下单”。
测试 B:反向用例(登录失败)
- 修改登录接口参数为错误的密码(如
admin/error)。 - 运行脚本。
- 观察:
- “API_登录” 执行,但业务码不是 200。
- 关键点:在结果树中,完全看不到 “API_下单” 的记录。
- 这说明 If 控制器成功拦截了请求,脚本实现了智能止损。
5.5. 本章小结
本章我们给脚本赋予了 “判断能力” 和 “决策能力”。
核心要点:
- HTTP 200 不等于成功:压测必须基于业务指标,使用 响应断言 或 JSON 断言 来修正成功率统计。
- 断言选择:简单的文本包含用响应断言;复杂的 JSON 字段校验用 JSON 断言。
- If 控制器:用于构建依赖链路,避免上游失败后下游继续无效执行,节省压测机资源。
下一步计划:目前我们的脚本已经非常健壮了,不仅能传参,还能自动判断对错。但是,它们还只能运行在标准 Java 代码无法解决的逻辑上。比如:“我想对密码进行 RSA 加密后再发送”,或者 “我想直接连数据库清理垃圾数据”。这些需求靠标准组件很难实现。在下一章,我们将解锁 JMeter 的核武器——JSR223 + Groovy 脚本编程。











