--
:
--
:
--
JMeter断言测试详解
最后更新于:
JMeter断言测试详解
一、断言概述
1.1 什么是断言
断言(Assertions)是JMeter中用于验证采样器响应是否符合预期的元件,用于判断测试是否通过。
1.2 断言的作用
- 验证响应数据:验证响应内容是否正确
- 检查响应码:验证HTTP响应码是否符合预期
- 验证响应时间:验证响应时间是否在允许范围内
- 检查数据完整性:验证数据是否完整
- 确保测试质量:确保系统行为符合预期
1.3 断言执行顺序
1断言执行顺序:
21. 采样器执行完成
32. 后置处理器执行(如果有)
43. 断言执行(按在测试计划树中的顺序)
54. 监听器收集结果1.4 断言分类
| 类型 | 断言名称 | 说明 |
|---|---|---|
| 响应断言 | 响应断言、JSON断言、XPath断言 | 验证响应内容 |
| 代码断言 | JSR223断言、BeanShell断言 | 使用脚本进行断言 |
| 时间断言 | 响应时间断言 | 验证响应时间 |
| 大小断言 | 响应大小断言 | 验证响应大小 |
| HTML断言 | HTML断言 | 验证HTML结构 |
二、响应断言
2.1 添加响应断言
1右键点击采样器 → Add → Assertions → Response Assertion2.2 配置
1名称: 响应断言
2响应字段: 响应文本
3匹配规则: 包含
4测试模式:
5 http://example.com2.3 参数说明
响应字段(Response Field to Test)
1响应字段: 响应文本选项:
- 响应文本(Text Response):响应内容(默认)
- 响应代码(Response Code):HTTP响应码
- 响应消息(Response Message):HTTP响应消息
- 响应头(Response Headers):响应头
- 请求头(Request Headers):请求头
- URL样本(URL Sample):请求URL
- 文档文本(Document Text):HTML解析后的文本
匹配规则(Pattern Matching Rules)
1匹配规则: 包含选项:
- 包含(Contains):响应中包含匹配模式
- 匹配(Matches):响应完全匹配正则表达式
- Equals:响应完全等于测试模式
- Substring:响应包含测试模式作为子字符串
- 否(Not):对结果取反
- Or:多个测试模式满足任意一个即可
测试模式(Test Pattern)
1测试模式:
2 http://example.com
3 success说明:要匹配的模式,可以是字符串或正则表达式。
2.4 使用场景
验证响应包含指定文本
1测试计划结构示例:
2测试计划
3├── 线程组
4│ ├── HTTP请求(登录)
5│ └── 响应断言
6│ 响应字段: 响应文本
7│ 匹配规则: 包含
8│ 测试模式: success验证响应码
1测试计划结构示例:
2测试计划
3├── 线程组
4│ ├── HTTP请求(登录)
5│ └── 响应断言
6│ 响应字段: 响应代码
7│ 匹配规则: Equals
8│ 测试模式: 200验证响应消息
1测试计划结构示例:
2测试计划
3├── 线程组
4│ ├── HTTP请求(登录)
5│ └── 响应断言
6│ 响应字段: 响应消息
7│ 匹配规则: Equals
8│ 测试模式: OK三、JSON断言
3.1 添加JSON断言
1右键点击采样器 → Add → Assertions → JSON Assertion3.2 配置
1名称: JSON断言
2JSON路径表达式: $.code
3期望值: 0
4匹配规则: 严格相等3.3 参数说明
JSON路径表达式(JSON Path Expression)
1JSON路径表达式: $.code说明:JSON路径表达式,用于定位JSON中的字段。
常用JSON Path表达式:
| 表达式 | 说明 | 示例 |
|---|---|---|
$.key | 获取根对象的key字段 | $.code |
$.data[0] | 获取data数组的第一个元素 | $.data[0].name |
$.data[*] | 获取data数组的所有元素 | $.data[*].id |
$.data.length() | 获取data数组的长度 | $.data.length() |
$..name | 获取所有name字段 | $..name |
期望值(Expected Value)
1期望值: 0说明:期望的字段值。
匹配规则(Match Type)
1匹配规则: 严格相等选项:
- 严格相等(Equals):值完全相等
- 包含(Contains):值包含期望值
- 匹配(Matches):值匹配正则表达式
- 小于(Less Than):值小于期望值
- 大于(Greater Than):值大于期望值
附加断言(Additional Assertions)
1勾选: 存在(Exists)
2勾选: 为数字(Is Number)
3勾选: 不为空(Not Null)说明:附加的断言条件。
3.4 使用场景
验证JSON响应字段
1{
2 "code": 0,
3 "message": "success",
4 "data": {
5 "id": 1,
6 "name": "test"
7 }
8}1测试计划结构示例:
2测试计划
3├── 线程组
4│ ├── HTTP请求(获取用户信息)
5│ └── JSON断言
6│ JSON路径表达式: $.code
7│ 期望值: 0
8│ 匹配规则: 严格相等验证数组长度
1{
2 "code": 0,
3 "data": {
4 "list": [
5 {"id": 1},
6 {"id": 2},
7 {"id": 3}
8 ]
9 }
10}1测试计划结构示例:
2测试计划
3├── 线程组
4│ ├── HTTP请求(获取用户列表)
5│ └── JSON断言
6│ JSON路径表达式: $.data.list.length()
7│ 期望值: 3
8│ 匹配规则: 严格相等四、XPath断言
4.1 添加XPath断言
1右键点击采样器 → Add → Assertions → XPath Assertion4.2 配置
1名称: XPath断言
2XPath表达式: //code/text()
3期望值: 04.3 参数说明
XPath表达式(XPath Expression)
1XPath表达式: //code/text()说明:XPath表达式,用于定位XML/HTML中的元素。
期望值(Expected Value)
1期望值: 0说明:期望的元素值。
忽略空白(Ignore Whitespace)
1勾选: 忽略空白说明:如果勾选,忽略XML/HTML中的空白字符。
4.4 使用场景
验证XML响应
1<response>
2 <code>0</code>
3 <message>success</message>
4 <data>
5 <user>
6 <name>test</name>
7 </user>
8 </data>
9</response>1测试计划结构示例:
2测试计划
3├── 线程组
4│ ├── HTTP请求(获取用户信息)
5│ └── XPath断言
6│ XPath表达式: //code/text()
7│ 期望值: 0验证HTML响应
1<html>
2 <body>
3 <div class="content">
4 <span id="user-name">testuser</span>
5 </div>
6 </body>
7</html>1测试计划结构示例:
2测试计划
3├── 线程组
4│ ├── HTTP请求(获取页面)
5│ └── XPath断言
6│ XPath表达式: //span[@id='user-name']/text()
7│ 期望值: testuser五、JSR223断言
5.1 添加JSR223断言
1右键点击采样器 → Add → Assertions → JSR223 Assertion5.2 配置
1名称: JSR223断言
2脚本语言: groovy
3脚本:
4 // 获取响应数据
5 def response = prev.getResponseDataAsString()
6
7 // 解析JSON
8 def json = new groovy.json.JsonSlurper().parseText(response)
9
10 // 验证code字段
11 if (json.code != 0) {
12 AssertionResult.setFailure(true)
13 AssertionResult.setFailureMessage("Expected code=0, but got ${json.code}")
14 }
15
16 // 验证data字段存在
17 if (json.data == null) {
18 AssertionResult.setFailure(true)
19 AssertionResult.setFailureMessage("data field is null")
20 }5.3 参数说明
脚本语言(Language)
1脚本语言: groovy选项:
- groovy(推荐):性能最好
- javascript:JavaScript语言
- beanshell:BeanShell语言
脚本(Script)
1// 脚本内容说明:要执行的脚本代码。
5.4 可用变量
| 变量 | 说明 | 示例 |
|---|---|---|
| vars | JMeter变量对象 | vars.get("name") |
| props | JMeter属性对象 | props.get("jmeter.home") |
| log | 日志对象 | log.info("message") |
| ctx | JMeter上下文对象 | ctx.getThreadNum() |
| prev | 前一个采样器的结果对象 | prev.getResponseDataAsString() |
| AssertionResult | 断言结果对象 | AssertionResult.setFailure(true) |
5.5 使用场景
复杂断言逻辑
1// 获取响应数据
2def response = prev.getResponseDataAsString()
3
4// 解析JSON
5def json = new groovy.json.JsonSlurper().parseText(response)
6
7// 验证响应码
8if (prev.getResponseCode() != "200") {
9 AssertionResult.setFailure(true)
10 AssertionResult.setFailureMessage("Response code is ${prev.getResponseCode()}")
11}
12
13// 验证code字段
14if (json.code != 0) {
15 AssertionResult.setFailure(true)
16 AssertionResult.setFailureMessage("Expected code=0, but got ${json.code}")
17}
18
19// 验证data字段不为空
20if (!json.data || json.data.isEmpty()) {
21 AssertionResult.setFailure(true)
22 AssertionResult.setFailureMessage("data field is empty")
23}
24
25// 验证用户ID在1-1000范围内
26def userId = json.data.id
27if (userId < 1 || userId > 1000) {
28 AssertionResult.setFailure(true)
29 AssertionResult.setFailureMessage("User ID ${userId} is out of range")
30}
31
32// 验证用户名不为空
33def userName = json.data.name
34if (!userName || userName.trim().isEmpty()) {
35 AssertionResult.setFailure(true)
36 AssertionResult.setFailureMessage("User name is empty")
37}动态断言
1// 获取期望的用户ID
2def expectedUserId = vars.get("expected_user_id")
3
4// 获取响应数据
5def response = prev.getResponseDataAsString()
6
7// 解析JSON
8def json = new groovy.json.JsonSlurper().parseText(response)
9
10// 验证用户ID
11if (json.data.id != expectedUserId.toInteger()) {
12 AssertionResult.setFailure(true)
13 AssertionResult.setFailureMessage("Expected user_id=${expectedUserId}, but got ${json.data.id}")
14}六、BeanShell断言
6.1 添加BeanShell断言
1右键点击采样器 → Add → Assertions → BeanShell Assertion6.2 配置
1名称: BeanShell断言
2脚本:
3 // 获取响应数据
4 String response = prev.getResponseDataAsString();
5
6 // 验证响应包含success
7 if (!response.contains("success")) {
8 Failure = true;
9 FailureMessage = "Response does not contain 'success'";
10 }6.3 使用场景
注意:推荐使用JSR223断言(Groovy语言),性能比BeanShell好。
七、响应时间断言
7.1 添加响应时间断言
1右键点击采样器 → Add → Assertions → Duration Assertion7.2 配置
1名称: 响应时间断言
2持续时间(毫秒): 50007.3 参数说明
持续时间(Duration)
1持续时间(毫秒): 5000说明:允许的最大响应时间(毫秒)。
7.4 使用场景
1测试计划结构示例:
2测试计划
3├── 线程组
4│ ├── HTTP请求(查询订单)
5│ └── 响应时间断言
6│ 持续时间: 5000(5秒)效果:如果响应时间超过5秒,测试失败。
八、响应大小断言
8.1 添加响应大小断言
1右键点击采样器 → Add → Assertions → Size Assertion8.2 配置
1名称: 响应大小断言
2响应大小字段: 响应字节数
3比较类型: <=
4大小(字节): 102400(100KB)8.3 参数说明
响应大小字段(Response Size Field to Test)
1响应大小字段: 响应字节数选项:
- 响应字节数(Response Size in Bytes):响应体大小
- 响应行数(Response Size in Lines):响应体行数
比较类型(Comparison Type)
1比较类型: <=选项:
- ==:等于
- !=:不等于
- >:大于
- >=:大于等于
- <:小于
- <=:小于等于
大小(Size)
1大小(字节): 102400说明:期望的响应大小(字节或行数)。
8.4 使用场景
1测试计划结构示例:
2测试计划
3├── 线程组
4│ ├── HTTP请求(下载文件)
5│ └── 响应大小断言
6│ 响应大小字段: 响应字节数
7│ 比较类型: <=
8│ 大小: 102400(100KB)效果:如果响应大小超过100KB,测试失败。
九、HTML断言
9.1 添加HTML断言
1右键点击采样器 → Add → Assertions → HTML Assertion9.2 配置
1名称: HTML断言
2解析器: NekoHTML9.3 参数说明
解析器(Parser)
1解析器: NekoHTML选项:
- NekoHTML:NekoHTML解析器(默认)
- Tidy:Tidy解析器
9.4 使用场景
1验证HTML响应是否合法。十、断言作用域
10.1 采样器级别断言
1添加位置: 采样器级别
2作用域: 仅该采样器10.2 控制器级别断言
1添加位置: 控制器级别
2作用域: 控制器内所有采样器10.3 线程组级别断言
1添加位置: 线程组级别
2作用域: 线程组内所有采样器10.4 测试计划级别断言
1添加位置: 测试计划级别
2作用域: 所有线程组十一、实战案例
11.1 案例1:完整的接口测试断言
需求:测试用户登录接口,验证响应数据
配置步骤:
创建线程组(10线程,循环1次)
添加HTTP请求(登录):
1方法: POST
2路径: /api/login
3Body Data:
4 {
5 "username": "admin",
6 "password": "admin123"
7 }- 添加响应断言(验证响应码):
1响应字段: 响应代码
2匹配规则: Equals
3测试模式: 200- 添加响应断言(验证响应消息):
1响应字段: 响应消息
2匹配规则: Equals
3测试模式: OK- 添加JSON断言(验证code字段):
1JSON路径表达式: $.code
2期望值: 0
3匹配规则: 严格相等- 添加JSON断言(验证token字段存在):
1JSON路径表达式: $.data.token
2附加断言: 存在
3附加断言: 不为空- 添加JSR223断言(验证响应时间):
1if (prev.getTime() > 3000) {
2 AssertionResult.setFailure(true)
3 AssertionResult.setFailureMessage("Response time ${prev.getTime()}ms exceeds 3000ms")
4}添加查看结果树
运行测试
11.2 案例2:用户管理接口断言测试
需求:测试用户管理接口,验证CRUD操作
配置步骤:
创建线程组(10线程,循环1次)
添加HTTP请求(创建用户):
1方法: POST
2路径: /api/users
3Body Data:
4 {
5 "username": "testuser",
6 "email": "test@example.com",
7 "password": "123456"
8 }- 添加JSON断言(验证创建成功):
1JSON路径表达式: $.code
2期望值: 0
3匹配规则: 严格相等- 添加JSON提取器(提取用户ID):
1引用名称: user_id
2JSON路径表达式: $.data.id- 添加HTTP请求(获取用户信息):
1方法: GET
2路径: /api/users/${user_id}- 添加JSON断言(验证用户信息):
1JSON路径表达式: $.code
2期望值: 0
3
4JSON路径表达式: $.data.username
5期望值: testuser
6
7JSON路径表达式: $.data.email
8期望值: test@example.com- 添加HTTP请求(更新用户信息):
1方法: PUT
2路径: /api/users/${user_id}
3Body Data:
4 {
5 "username": "updateduser",
6 "email": "updated@example.com"
7 }- 添加JSON断言(验证更新成功):
1JSON路径表达式: $.code
2期望值: 0- 添加HTTP请求(删除用户):
1方法: DELETE
2路径: /api/users/${user_id}- 添加JSON断言(验证删除成功):
1JSON路径表达式: $.code
2期望值: 0添加查看结果树
运行测试
11.3 案例3:复杂业务逻辑断言
需求:测试订单创建接口,验证业务逻辑
配置步骤:
创建线程组(10线程,循环1次)
添加JSR223前置处理器(生成测试数据):
1def orderId = UUID.randomUUID().toString()
2vars.put("order_id", orderId)
3vars.put("amount", "100.00")
4vars.put("product_id", "1")
5vars.put("quantity", "1")- 添加HTTP请求(创建订单):
1方法: POST
2路径: /api/orders
3Body Data:
4 {
5 "order_id": "${order_id}",
6 "product_id": "${product_id}",
7 "quantity": ${quantity},
8 "amount": ${amount}
9 }- 添加JSR223断言(验证订单创建):
1def response = prev.getResponseDataAsString()
2def json = new groovy.json.JsonSlurper().parseText(response)
3
4// 验证响应码
5if (prev.getResponseCode() != "200") {
6 AssertionResult.setFailure(true)
7 AssertionResult.setFailureMessage("Response code is ${prev.getResponseCode()}")
8}
9
10// 验证code字段
11if (json.code != 0) {
12 AssertionResult.setFailure(true)
13 AssertionResult.setFailureMessage("Expected code=0, but got ${json.code}: ${json.message}")
14}
15
16// 验证订单数据
17def order = json.data
18if (!order) {
19 AssertionResult.setFailure(true)
20 AssertionResult.setFailureMessage("Order data is null")
21 return
22}
23
24// 验证订单ID
25if (order.order_id != vars.get("order_id")) {
26 AssertionResult.setFailure(true)
27 AssertionResult.setFailureMessage("Order ID mismatch")
28}
29
30// 验证商品ID
31if (order.product_id != vars.get("product_id").toInteger()) {
32 AssertionResult.setFailure(true)
33 AssertionResult.setFailureMessage("Product ID mismatch")
34}
35
36// 验证数量
37if (order.quantity != vars.get("quantity").toInteger()) {
38 AssertionResult.setFailure(true)
39 AssertionResult.setFailureMessage("Quantity mismatch")
40}
41
42// 验证金额(允许0.01的误差)
43def expectedAmount = vars.get("amount").toDouble()
44def actualAmount = order.amount
45if (Math.abs(expectedAmount - actualAmount) > 0.01) {
46 AssertionResult.setFailure(true)
47 AssertionResult.setFailureMessage("Amount mismatch: expected ${expectedAmount}, got ${actualAmount}")
48}
49
50// 验证订单状态
51if (order.status != "PENDING") {
52 AssertionResult.setFailure(true)
53 AssertionResult.setFailureMessage("Order status should be PENDING, but got ${order.status}")
54}
55
56// 验证创建时间
57if (!order.created_at) {
58 AssertionResult.setFailure(true)
59 AssertionResult.setFailureMessage("Created at is null")
60}
61
62log.info("Order created successfully: ${order.order_id}")添加查看结果树
运行测试
十二、常见问题
12.1 断言失败但实际响应正确
回答:
- 检查断言配置是否正确
- 检查响应字段是否选择正确
- 检查匹配规则是否正确
- 检查期望值是否正确
12.2 响应时间断言过于严格
回答:
- 根据实际情况调整响应时间阈值
- 使用JSR223断言实现更灵活的时间验证
- 考虑网络延迟和服务器负载
12.3 JSON断言提取不到字段
回答:
- 检查JSON路径表达式是否正确
- 检查响应是否为有效的JSON格式
- 使用调试后置处理器查看响应内容
12.4 断言影响性能
回答:
- 尽量使用简单的断言
- 避免在断言中执行复杂的计算
- 性能测试时可以减少断言数量
下一章:13-定时器详解.md
📡
👤
作者:
阿海
🌐
版权:
本站文章除特别声明外,均采用
CC BY-NC-SA 4.0
协议,转载请注明来自
阿海 Blog!
- 01JMeter界面详解 2026-07-11
- 02性能测试学习路线 2026-07-11
- 03JMeter线程组配置详解 2026-07-11