--
:
--
:
--
JMeter参数化测试详解
最后更新于:
JMeter参数化测试详解
一、参数化测试概述
1.1 什么是参数化测试
参数化测试是指在测试过程中使用不同的参数值来执行相同的测试脚本,以验证系统在不同输入下的行为。
1.2 参数化测试的作用
- 增加测试覆盖:使用不同的参数值测试系统
- 模拟真实场景:模拟不同用户的行为
- 数据驱动测试:将测试数据与测试逻辑分离
- 提高测试效率:一次执行多个测试用例
1.3 参数化测试方法
| 方法 | 说明 | 适用场景 |
|---|---|---|
| CSV数据文件 | 从CSV文件读取测试数据 | 大量测试数据 |
| 用户定义变量 | 在测试计划中定义变量 | 少量固定数据 |
| 函数生成 | 使用JMeter函数生成数据 | 动态数据生成 |
| 数据库查询 | 从数据库读取测试数据 | 从数据库获取数据 |
| JSR223脚本 | 使用脚本生成数据 | 复杂数据生成 |
二、CSV数据文件参数化
2.1 创建CSV数据文件
1username,password,email
2admin,admin123,admin@example.com
3user1,user123,user1@example.com
4user2,user234,user2@example.com
5user3,user345,user3@example.com
6user4,user456,user4@example.com
7user5,user567,user5@example.com2.2 添加CSV数据设置
1右键点击线程组 → Add → Config Element → CSV Data Set Config2.3 配置
1名称: CSV数据设置
2文件名: users.csv
3文件编码: UTF-8
4变量名称: username,password,email
5分隔符: ,
6允许带引号: true
7遇到文件结束符再次循环: true
8遇到文件结束符停止线程: false
9线程共享模式: All threads2.4 参数说明
文件名(Filename)
1文件名: users.csv说明:CSV文件的路径。可以使用绝对路径或相对路径。
示例:
1绝对路径: C:\test\users.csv
2相对路径: users.csv(相对于JMeter工作目录)文件编码(File Encoding)
1文件编码: UTF-8说明:CSV文件的编码格式。
选项:
- UTF-8:UTF-8编码(默认)
- GBK:中文编码
- ISO-8859-1:ISO编码
变量名称(Variable Names)
1变量名称: username,password,email说明:CSV文件中列的名称,用逗号分隔。
注意:变量名称必须与CSV文件的列顺序对应。
分隔符(Delimiter)
1分隔符: ,说明:CSV文件的列分隔符。
选项:
- ,:逗号分隔(默认)
- ;:分号分隔
- \t:制表符分隔
允许带引号(Allow quoted data?)
1勾选: 允许带引号说明:如果勾选,CSV文件中的值可以用引号包围。
示例:
1username,password,email
2"test,user",123456,"test@example.com"遇到文件结束符再次循环(Recycle on EOF?)
1勾选: 遇到文件结束符再次循环说明:如果勾选,当读取到文件末尾时,重新从文件开头读取。
遇到文件结束符停止线程(Stop thread on EOF?)
1勾选: 遇到文件结束符停止线程说明:如果勾选,当读取到文件末尾时,停止线程。
线程共享模式(Sharing Mode)
1线程共享模式: All threads选项:
- All threads:所有线程共享同一个文件指针
- Current thread group:当前线程组共享文件指针
- Current thread:每个线程独立使用文件
2.5 使用场景
用户登录测试
1测试计划结构示例:
2测试计划
3├── 线程组(10线程,循环5次)
4│ ├── CSV数据设置
5│ │ 文件名: users.csv
6│ │ 变量名称: username,password,email
7│ └── HTTP请求(登录)
8│ 方法: POST
9│ 路径: /api/login
10│ 参数:
11│ username: ${username}
12│ password: ${password}效果:每个线程使用不同的用户数据登录。
三、用户定义变量参数化
3.1 添加用户定义的变量
1右键点击线程组 → Add → Config Element → User Defined Variables3.2 配置
1名称: 测试数据变量
2
3变量列表:
4 名称: username
5 值: ${__RandomFromMultipleVars(user1,user2,user3,user4,user5)}
6
7 名称: password
8 值: 123456
9
10 名称: email
11 值: ${username}@example.com3.3 使用场景
少量固定数据测试
1测试计划结构示例:
2测试计划
3├── 线程组(10线程,循环10次)
4│ ├── 用户定义的变量
5│ │ ├── base_url = http://localhost:8080
6│ │ ├── api_version = v1
7│ │ └── timeout = 30000
8│ └── HTTP请求
9│ 服务器名称: ${base_url}
10│ 路径: /${api_version}/users四、函数参数化
4.1 使用__Random函数
1${__Random(1,1000)}示例:
1测试计划结构示例:
2测试计划
3├── 线程组(100线程,循环10次)
4│ └── HTTP请求(查询用户)
5│ 方法: GET
6│ 路径: /api/users/${__Random(1,1000)}4.2 使用__RandomString函数
1${__RandomString(10,abcdefghijklmnopqrstuvwxyz)}示例:
1测试计划结构示例:
2测试计划
3├── 线程组(100线程,循环10次)
4│ └── HTTP请求(创建用户)
5│ 方法: POST
6│ 路径: /api/users
7│ Body Data:
8│ {
9│ "username": "${__RandomString(10,abcdefghijklmnopqrstuvwxyz)}",
10│ "email": "${__RandomString(8,abcdefghijklmnopqrstuvwxyz)}@example.com",
11│ "password": "${__RandomString(8,ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789)}"
12│ }4.3 使用__UUID函数
1${__UUID()}示例:
1测试计划结构示例:
2测试计划
3├── 线程组(100线程,循环10次)
4│ └── HTTP请求(创建订单)
5│ 方法: POST
6│ 路径: /api/orders
7│ Body Data:
8│ {
9│ "order_id": "${__UUID()}",
10│ "amount": ${__Random(100,10000)}
11│ }4.4 使用__time函数
1${__time(yyyy-MM-dd HH:mm:ss)}示例:
1测试计划结构示例:
2测试计划
3├── 线程组(100线程,循环10次)
4│ └── HTTP请求(查询日志)
5│ 方法: GET
6│ 路径: /api/logs
7│ 参数:
8│ start_time: ${__timeShift(yyyy-MM-dd HH:mm:ss,-1,h,)}
9│ end_time: ${__time(yyyy-MM-dd HH:mm:ss)}五、数据库参数化
5.1 添加JDBC连接配置
1名称: JDBC连接配置
2变量名: mysql_db
3JDBC驱动类: com.mysql.cj.jdbc.Driver
4JDBC URL: jdbc:mysql://localhost:3306/test
5用户名: root
6密码: password5.2 添加JDBC请求
1名称: 查询用户数据
2变量名: mysql_db
3查询类型: Select Statement
4查询语句: SELECT username, password FROM users WHERE status = 1 ORDER BY RAND() LIMIT 1;
5结果变量名: user_data5.3 使用数据库数据
1// 在JSR223后置处理器中使用数据库查询结果
2def username = vars.getObject("user_data").get(0).get("username")
3def password = vars.getObject("user_data").get(0).get("password")
4vars.put("db_username", username)
5vars.put("db_password", password)5.4 使用场景
1测试计划结构示例:
2测试计划
3├── 线程组(100线程,循环10次)
4│ ├── JDBC连接配置
5│ ├── JDBC请求(查询用户)
6│ │ 查询语句: SELECT username, password FROM users WHERE status = 1 ORDER BY RAND() LIMIT 1;
7│ │ 结果变量名: user_data
8│ ├── JSR223后置处理器(提取数据)
9│ └── HTTP请求(登录)
10│ 参数:
11│ username: ${db_username}
12│ password: ${db_password}六、JSR223脚本参数化
6.1 添加JSR223前置处理器
1名称: 生成测试数据
2脚本语言: groovy
3脚本:
4 // 生成随机用户名
5 def chars = 'abcdefghijklmnopqrstuvwxyz'
6 def username = (1..10).collect { chars[new Random().nextInt(chars.size())] }.join()
7 vars.put("username", username)
8
9 // 生成随机邮箱
10 vars.put("email", "${username}@example.com")
11
12 // 生成随机密码
13 def passwordChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
14 def password = (1..8).collect { passwordChars[new Random().nextInt(passwordChars.size())] }.join()
15 vars.put("password", password)
16
17 // 生成随机年龄
18 vars.put("age", (18..60).getAt(new Random().nextInt(43)).toString())
19
20 // 生成随机手机号
21 def phone = "1${[3,4,5,7,8].getAt(new Random().nextInt(5))}" + (1..9).collect { new Random().nextInt(10) }.join()
22 vars.put("phone", phone)6.2 使用场景
复杂数据生成
1测试计划结构示例:
2测试计划
3├── 线程组(100线程,循环10次)
4│ ├── JSR223前置处理器(生成数据)
5│ └── HTTP请求(创建用户)
6│ 方法: POST
7│ 路径: /api/users
8│ Body Data:
9│ {
10│ "username": "${username}",
11│ "email": "${email}",
12│ "password": "${password}",
13│ "age": ${age},
14│ "phone": "${phone}"
15│ }七、参数化测试最佳实践
7.1 数据准备
11. 确保测试数据的真实性和多样性
22. 准备足够的测试数据
33. 数据格式要符合接口要求
44. 敏感数据要加密处理7.2 参数化策略
11. 根据测试场景选择合适的参数化方法
22. 对于大量数据使用CSV文件
33. 对于动态数据使用函数或脚本
44. 对于数据库数据使用JDBC请求7.3 数据管理
11. 测试数据与测试脚本分离
22. 使用版本控制管理测试数据
33. 定期更新测试数据
44. 清理测试产生的数据7.4 性能考虑
11. CSV文件不要过大(建议小于1GB)
22. 使用线程共享模式减少文件读取次数
33. 避免在循环中频繁读取数据库
44. 使用缓存减少重复数据生成八、实战案例
8.1 案例1:用户登录参数化测试
需求:使用CSV文件测试多个用户登录
配置步骤:
- 创建CSV数据文件(users.csv):
1username,password
2admin,admin123
3user1,user123
4user2,user234
5user3,user345
6user4,user456
7user5,user567
8user6,user678
9user7,user789
10user8,user890
11user9,user901
12user10,user1011创建线程组(10线程,循环10次)
添加CSV数据设置:
1文件名: users.csv
2变量名称: username,password
3分隔符: ,
4遇到文件结束符再次循环: true
5线程共享模式: All threads- 添加HTTP请求(登录):
1方法: POST
2路径: /api/login
3参数:
4 username: ${username}
5 password: ${password}添加聚合报告
运行测试
8.2 案例2:动态数据参数化测试
需求:测试创建用户接口,使用动态生成的数据
配置步骤:
创建线程组(50线程,循环5次)
添加JSR223前置处理器:
1def chars = 'abcdefghijklmnopqrstuvwxyz'
2def username = (1..10).collect { chars[new Random().nextInt(chars.size())] }.join()
3vars.put("username", username)
4
5vars.put("email", "${username}@example.com")
6
7def passwordChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
8def password = (1..8).collect { passwordChars[new Random().nextInt(passwordChars.size())] }.join()
9vars.put("password", password)
10
11vars.put("age", (18..60).getAt(new Random().nextInt(43)).toString())
12
13def phone = "1${[3,4,5,7,8].getAt(new Random().nextInt(5))}" + (1..9).collect { new Random().nextInt(10) }.join()
14vars.put("phone", phone)- 添加HTTP请求(创建用户):
1方法: POST
2路径: /api/users
3Body Data:
4 {
5 "username": "${username}",
6 "email": "${email}",
7 "password": "${password}",
8 "age": ${age},
9 "phone": "${phone}"
10 }添加聚合报告
运行测试
8.3 案例3:数据库数据参数化测试
需求:从数据库读取用户数据进行登录测试
配置步骤:
下载MySQL驱动并复制到lib目录
创建线程组(100线程,循环10次)
添加JDBC连接配置:
1变量名: mysql_db
2JDBC驱动类: com.mysql.cj.jdbc.Driver
3JDBC URL: jdbc:mysql://localhost:3306/test
4用户名: root
5密码: password- 添加JDBC请求(查询用户):
1变量名: mysql_db
2查询类型: Select Statement
3查询语句: SELECT username, password FROM users WHERE status = 1 ORDER BY RAND() LIMIT 1;
4结果变量名: user_data- 添加JSR223后置处理器(提取数据):
1def result = vars.getObject("user_data")
2if (result != null && !result.isEmpty()) {
3 def row = result.get(0)
4 vars.put("db_username", row.get("username"))
5 vars.put("db_password", row.get("password"))
6} else {
7 vars.put("db_username", "admin")
8 vars.put("db_password", "admin123")
9}- 添加HTTP请求(登录):
1方法: POST
2路径: /api/login
3参数:
4 username: ${db_username}
5 password: ${db_password}添加聚合报告
运行测试
九、常见问题
9.1 CSV文件读取失败
回答:
- 检查文件路径是否正确
- 检查文件编码是否正确
- 检查分隔符是否正确
- 确保文件存在且可读
9.2 变量值为空
回答:
- 检查变量名称是否正确
- 检查CSV文件是否有数据
- 检查文件编码是否正确
- 使用调试后置处理器查看变量值
9.3 数据重复
回答:
- 增加CSV文件中的数据量
- 使用随机函数生成数据
- 使用数据库查询获取数据
- 调整线程共享模式
9.4 性能问题
回答:
- 使用较小的CSV文件
- 使用线程共享模式
- 避免频繁读取数据库
- 使用缓存机制
下一章:12-断言测试.md
📡
👤
作者:
阿海
🌐
版权:
本站文章除特别声明外,均采用
CC BY-NC-SA 4.0
协议,转载请注明来自
阿海 Blog!
- 01JMeter界面详解 2026-07-11
- 02性能测试学习路线 2026-07-11
- 03JMeter线程组配置详解 2026-07-11