头像
淇迹时刻
-- : -- : --
切换主题色
-- : -- : --

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 Assertion

2.2 配置

1名称: 响应断言
2响应字段: 响应文本
3匹配规则: 包含
4测试模式: 
5    http://example.com

2.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 Assertion

3.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 Assertion

4.2 配置

1名称: XPath断言
2XPath表达式: //code/text()
3期望值: 0

4.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 Assertion

5.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 可用变量

变量说明示例
varsJMeter变量对象vars.get("name")
propsJMeter属性对象props.get("jmeter.home")
log日志对象log.info("message")
ctxJMeter上下文对象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 Assertion

6.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 Assertion

7.2 配置

1名称: 响应时间断言
2持续时间(毫秒): 5000

7.3 参数说明

持续时间(Duration)

1持续时间(毫秒): 5000

说明:允许的最大响应时间(毫秒)。

7.4 使用场景

1测试计划结构示例:
2测试计划
3├── 线程组
4│   ├── HTTP请求(查询订单)
5│   └── 响应时间断言
6│       持续时间: 5000(5秒)

效果:如果响应时间超过5秒,测试失败。

八、响应大小断言

8.1 添加响应大小断言

1右键点击采样器 → Add → Assertions → Size Assertion

8.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 Assertion

9.2 配置

1名称: HTML断言
2解析器: NekoHTML

9.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:完整的接口测试断言

需求:测试用户登录接口,验证响应数据

配置步骤

  1. 创建线程组(10线程,循环1次)

  2. 添加HTTP请求(登录):

1方法: POST
2路径: /api/login
3Body Data:
4    {
5        "username": "admin",
6        "password": "admin123"
7    }
  1. 添加响应断言(验证响应码):
1响应字段: 响应代码
2匹配规则: Equals
3测试模式: 200
  1. 添加响应断言(验证响应消息):
1响应字段: 响应消息
2匹配规则: Equals
3测试模式: OK
  1. 添加JSON断言(验证code字段):
1JSON路径表达式: $.code
2期望值: 0
3匹配规则: 严格相等
  1. 添加JSON断言(验证token字段存在):
1JSON路径表达式: $.data.token
2附加断言: 存在
3附加断言: 不为空
  1. 添加JSR223断言(验证响应时间):
1if (prev.getTime() > 3000) {
2    AssertionResult.setFailure(true)
3    AssertionResult.setFailureMessage("Response time ${prev.getTime()}ms exceeds 3000ms")
4}
  1. 添加查看结果树

  2. 运行测试

11.2 案例2:用户管理接口断言测试

需求:测试用户管理接口,验证CRUD操作

配置步骤

  1. 创建线程组(10线程,循环1次)

  2. 添加HTTP请求(创建用户):

1方法: POST
2路径: /api/users
3Body Data:
4    {
5        "username": "testuser",
6        "email": "test@example.com",
7        "password": "123456"
8    }
  1. 添加JSON断言(验证创建成功):
1JSON路径表达式: $.code
2期望值: 0
3匹配规则: 严格相等
  1. 添加JSON提取器(提取用户ID):
1引用名称: user_id
2JSON路径表达式: $.data.id
  1. 添加HTTP请求(获取用户信息):
1方法: GET
2路径: /api/users/${user_id}
  1. 添加JSON断言(验证用户信息):
1JSON路径表达式: $.code
2期望值: 0
3
4JSON路径表达式: $.data.username
5期望值: testuser
6
7JSON路径表达式: $.data.email
8期望值: test@example.com
  1. 添加HTTP请求(更新用户信息):
1方法: PUT
2路径: /api/users/${user_id}
3Body Data:
4    {
5        "username": "updateduser",
6        "email": "updated@example.com"
7    }
  1. 添加JSON断言(验证更新成功):
1JSON路径表达式: $.code
2期望值: 0
  1. 添加HTTP请求(删除用户):
1方法: DELETE
2路径: /api/users/${user_id}
  1. 添加JSON断言(验证删除成功):
1JSON路径表达式: $.code
2期望值: 0
  1. 添加查看结果树

  2. 运行测试

11.3 案例3:复杂业务逻辑断言

需求:测试订单创建接口,验证业务逻辑

配置步骤

  1. 创建线程组(10线程,循环1次)

  2. 添加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")
  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    }
  1. 添加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}")
  1. 添加查看结果树

  2. 运行测试

十二、常见问题

12.1 断言失败但实际响应正确

回答

  • 检查断言配置是否正确
  • 检查响应字段是否选择正确
  • 检查匹配规则是否正确
  • 检查期望值是否正确

12.2 响应时间断言过于严格

回答

  • 根据实际情况调整响应时间阈值
  • 使用JSR223断言实现更灵活的时间验证
  • 考虑网络延迟和服务器负载

12.3 JSON断言提取不到字段

回答

  • 检查JSON路径表达式是否正确
  • 检查响应是否为有效的JSON格式
  • 使用调试后置处理器查看响应内容

12.4 断言影响性能

回答

  • 尽量使用简单的断言
  • 避免在断言中执行复杂的计算
  • 性能测试时可以减少断言数量

下一章13-定时器详解.md

最新文章

本页导航