文章目录
- [11 接口参数化与数据驱动 - 一套用例,多种数据](#11 接口参数化与数据驱动 - 一套用例,多种数据)
-
- [11.1 什么是数据驱动测试](#11.1 什么是数据驱动测试)
- [11.2 为什么要做数据驱动](#11.2 为什么要做数据驱动)
- [11.3 数据源类型](#11.3 数据源类型)
- [11.4 Postman 数据驱动](#11.4 Postman 数据驱动)
-
- CSV数据文件
- [Collection Runner配置](#Collection Runner配置)
- Tests中使用数据
- [11.5 JMeter 数据驱动](#11.5 JMeter 数据驱动)
-
- [CSV Data Set Config](#CSV Data Set Config)
- 使用变量
- [11.6 Python 数据驱动](#11.6 Python 数据驱动)
- [11.7 数据驱动最佳实践](#11.7 数据驱动最佳实践)
- [11.8 本章小结](#11.8 本章小结)
-
- 数据驱动核心
- [课后练习 📝](#课后练习 📝)
- [11.9 下章预告](#11.9 下章预告)
11 接口参数化与数据驱动 - 一套用例,多种数据
🎯 本章目标:掌握数据驱动测试方法,学会用不同数据源驱动同一套测试用例。
11.1 什么是数据驱动测试
生活中的例子
想象一个自动售货机:
测试用例:投币 → 选择商品 → 出货
数据1:投5元 → 选可乐(3元) → 出可乐+找零2元
数据2:投10元 → 选薯片(8元) → 出薯片+找零2元
数据3:投2元 → 选可乐(3元) → 提示金额不足
同一套流程,不同的输入数据,不同的预期结果
数据驱动测试定义
数据驱动测试(Data-Driven Testing, DDT):将测试数据与测试逻辑分离,用不同的数据驱动同一套测试逻辑执行。
#mermaid-svg-alRpjQeJvS7FeM0n{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-alRpjQeJvS7FeM0n .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-alRpjQeJvS7FeM0n .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-alRpjQeJvS7FeM0n .error-icon{fill:#552222;}#mermaid-svg-alRpjQeJvS7FeM0n .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-alRpjQeJvS7FeM0n .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-alRpjQeJvS7FeM0n .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-alRpjQeJvS7FeM0n .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-alRpjQeJvS7FeM0n .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-alRpjQeJvS7FeM0n .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-alRpjQeJvS7FeM0n .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-alRpjQeJvS7FeM0n .marker{fill:#333333;stroke:#333333;}#mermaid-svg-alRpjQeJvS7FeM0n .marker.cross{stroke:#333333;}#mermaid-svg-alRpjQeJvS7FeM0n svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-alRpjQeJvS7FeM0n p{margin:0;}#mermaid-svg-alRpjQeJvS7FeM0n .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-alRpjQeJvS7FeM0n .cluster-label text{fill:#333;}#mermaid-svg-alRpjQeJvS7FeM0n .cluster-label span{color:#333;}#mermaid-svg-alRpjQeJvS7FeM0n .cluster-label span p{background-color:transparent;}#mermaid-svg-alRpjQeJvS7FeM0n .label text,#mermaid-svg-alRpjQeJvS7FeM0n span{fill:#333;color:#333;}#mermaid-svg-alRpjQeJvS7FeM0n .node rect,#mermaid-svg-alRpjQeJvS7FeM0n .node circle,#mermaid-svg-alRpjQeJvS7FeM0n .node ellipse,#mermaid-svg-alRpjQeJvS7FeM0n .node polygon,#mermaid-svg-alRpjQeJvS7FeM0n .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-alRpjQeJvS7FeM0n .rough-node .label text,#mermaid-svg-alRpjQeJvS7FeM0n .node .label text,#mermaid-svg-alRpjQeJvS7FeM0n .image-shape .label,#mermaid-svg-alRpjQeJvS7FeM0n .icon-shape .label{text-anchor:middle;}#mermaid-svg-alRpjQeJvS7FeM0n .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-alRpjQeJvS7FeM0n .rough-node .label,#mermaid-svg-alRpjQeJvS7FeM0n .node .label,#mermaid-svg-alRpjQeJvS7FeM0n .image-shape .label,#mermaid-svg-alRpjQeJvS7FeM0n .icon-shape .label{text-align:center;}#mermaid-svg-alRpjQeJvS7FeM0n .node.clickable{cursor:pointer;}#mermaid-svg-alRpjQeJvS7FeM0n .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-alRpjQeJvS7FeM0n .arrowheadPath{fill:#333333;}#mermaid-svg-alRpjQeJvS7FeM0n .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-alRpjQeJvS7FeM0n .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-alRpjQeJvS7FeM0n .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-alRpjQeJvS7FeM0n .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-alRpjQeJvS7FeM0n .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-alRpjQeJvS7FeM0n .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-alRpjQeJvS7FeM0n .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-alRpjQeJvS7FeM0n .cluster text{fill:#333;}#mermaid-svg-alRpjQeJvS7FeM0n .cluster span{color:#333;}#mermaid-svg-alRpjQeJvS7FeM0n div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-alRpjQeJvS7FeM0n .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-alRpjQeJvS7FeM0n rect.text{fill:none;stroke-width:0;}#mermaid-svg-alRpjQeJvS7FeM0n .icon-shape,#mermaid-svg-alRpjQeJvS7FeM0n .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-alRpjQeJvS7FeM0n .icon-shape p,#mermaid-svg-alRpjQeJvS7FeM0n .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-alRpjQeJvS7FeM0n .icon-shape .label rect,#mermaid-svg-alRpjQeJvS7FeM0n .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-alRpjQeJvS7FeM0n .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-alRpjQeJvS7FeM0n .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-alRpjQeJvS7FeM0n :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 测试逻辑
数据1
数据2
数据3
数据N
结果1
结果2
结果3
结果N
11.2 为什么要做数据驱动
传统测试的问题
python
# 传统方式:每个数据写一条用例
def test_login_1():
assert login("admin", "123456") == True
def test_login_2():
assert login("admin", "wrong") == False
def test_login_3():
assert login("", "123456") == False
# 问题:代码重复,维护困难
数据驱动方式
python
# 数据驱动:逻辑写一次,数据多套
test_data = [
("admin", "123456", True),
("admin", "wrong", False),
("", "123456", False),
]
@pytest.mark.parametrize("user,pwd,expected", test_data)
def test_login(user, pwd, expected):
assert login(user, pwd) == expected
数据驱动的好处
| 好处 | 说明 |
|---|---|
| 减少代码量 | 逻辑写一次,数据可扩展 |
| 易于维护 | 修改数据不用改代码 |
| 覆盖全面 | 轻松增加测试数据 |
| 分工明确 | 测试人员写数据,开发人员写逻辑 |
11.3 数据源类型
#mermaid-svg-vGrPDYrplk5ZrOWa{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vGrPDYrplk5ZrOWa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vGrPDYrplk5ZrOWa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vGrPDYrplk5ZrOWa .error-icon{fill:#552222;}#mermaid-svg-vGrPDYrplk5ZrOWa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vGrPDYrplk5ZrOWa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vGrPDYrplk5ZrOWa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vGrPDYrplk5ZrOWa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vGrPDYrplk5ZrOWa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vGrPDYrplk5ZrOWa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vGrPDYrplk5ZrOWa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vGrPDYrplk5ZrOWa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vGrPDYrplk5ZrOWa .marker.cross{stroke:#333333;}#mermaid-svg-vGrPDYrplk5ZrOWa svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vGrPDYrplk5ZrOWa p{margin:0;}#mermaid-svg-vGrPDYrplk5ZrOWa .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-vGrPDYrplk5ZrOWa .cluster-label text{fill:#333;}#mermaid-svg-vGrPDYrplk5ZrOWa .cluster-label span{color:#333;}#mermaid-svg-vGrPDYrplk5ZrOWa .cluster-label span p{background-color:transparent;}#mermaid-svg-vGrPDYrplk5ZrOWa .label text,#mermaid-svg-vGrPDYrplk5ZrOWa span{fill:#333;color:#333;}#mermaid-svg-vGrPDYrplk5ZrOWa .node rect,#mermaid-svg-vGrPDYrplk5ZrOWa .node circle,#mermaid-svg-vGrPDYrplk5ZrOWa .node ellipse,#mermaid-svg-vGrPDYrplk5ZrOWa .node polygon,#mermaid-svg-vGrPDYrplk5ZrOWa .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-vGrPDYrplk5ZrOWa .rough-node .label text,#mermaid-svg-vGrPDYrplk5ZrOWa .node .label text,#mermaid-svg-vGrPDYrplk5ZrOWa .image-shape .label,#mermaid-svg-vGrPDYrplk5ZrOWa .icon-shape .label{text-anchor:middle;}#mermaid-svg-vGrPDYrplk5ZrOWa .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vGrPDYrplk5ZrOWa .rough-node .label,#mermaid-svg-vGrPDYrplk5ZrOWa .node .label,#mermaid-svg-vGrPDYrplk5ZrOWa .image-shape .label,#mermaid-svg-vGrPDYrplk5ZrOWa .icon-shape .label{text-align:center;}#mermaid-svg-vGrPDYrplk5ZrOWa .node.clickable{cursor:pointer;}#mermaid-svg-vGrPDYrplk5ZrOWa .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-vGrPDYrplk5ZrOWa .arrowheadPath{fill:#333333;}#mermaid-svg-vGrPDYrplk5ZrOWa .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-vGrPDYrplk5ZrOWa .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-vGrPDYrplk5ZrOWa .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vGrPDYrplk5ZrOWa .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-vGrPDYrplk5ZrOWa .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vGrPDYrplk5ZrOWa .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-vGrPDYrplk5ZrOWa .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-vGrPDYrplk5ZrOWa .cluster text{fill:#333;}#mermaid-svg-vGrPDYrplk5ZrOWa .cluster span{color:#333;}#mermaid-svg-vGrPDYrplk5ZrOWa div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-vGrPDYrplk5ZrOWa .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vGrPDYrplk5ZrOWa rect.text{fill:none;stroke-width:0;}#mermaid-svg-vGrPDYrplk5ZrOWa .icon-shape,#mermaid-svg-vGrPDYrplk5ZrOWa .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vGrPDYrplk5ZrOWa .icon-shape p,#mermaid-svg-vGrPDYrplk5ZrOWa .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-vGrPDYrplk5ZrOWa .icon-shape .label rect,#mermaid-svg-vGrPDYrplk5ZrOWa .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vGrPDYrplk5ZrOWa .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vGrPDYrplk5ZrOWa .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vGrPDYrplk5ZrOWa :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 数据源
硬编码
文件
数据库
接口/API
代码中直接写
CSV/Excel/JSON/YAML
MySQL/Redis
外部系统提供
各种数据源对比
| 数据源 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 硬编码 | 简单直接 | 不易修改 | 少量固定数据 |
| CSV | 简单通用 | 不支持复杂结构 | 大量表格数据 |
| Excel | 可视化编辑 | 需要额外库 | 非技术人员维护 |
| JSON | 支持复杂结构 | 不易手动编辑 | 嵌套数据结构 |
| YAML | 可读性好 | 缩进敏感 | 配置文件 |
| 数据库 | 动态获取 | 依赖环境 | 动态测试数据 |
11.4 Postman 数据驱动
CSV数据文件
login_data.csv:
csv
username,password,expectedCode,description
admin,123456,0,正常登录
admin,wrong,1001,密码错误
,123456,1002,用户名为空
test,123,1003,用户不存在
admin,123,1004,密码过短
Collection Runner配置
- 准备CSV文件
- 打开Collection Runner
- 选择Data → Select File → 选择CSV
- 设置迭代次数(Iteration)
Tests中使用数据
javascript
// 获取当前迭代的数据
const username = pm.iterationData.get("username");
const password = pm.iterationData.get("password");
const expectedCode = parseInt(pm.iterationData.get("expectedCode"));
// 断言
pm.test(`测试: ${pm.iterationData.get("description")}`, function () {
const jsonData = pm.response.json();
pm.expect(jsonData.code).to.eql(expectedCode);
});
11.5 JMeter 数据驱动
CSV Data Set Config
CSV Data Set Config
├── Filename: login_data.csv
├── Variable Names: username,password,expectedCode
├── Delimiter: ,
├── Recycle on EOF: True
├── Stop thread on EOF: False
└── Sharing Mode: All threads
使用变量
HTTP请求
├── 路径: /api/v1/login
├── 方法: POST
└── Body Data:
{
"username": "${username}",
"password": "${password}"
}
响应断言
├── 测试字段: 响应文本
├── 模式匹配规则: 包含
└── 要测试的模式: "code":${expectedCode}
11.6 Python 数据驱动
pytest参数化
python
import pytest
import requests
# 测试数据
test_data = [
("admin", "123456", 0, "正常登录"),
("admin", "wrong", 1001, "密码错误"),
("", "123456", 1002, "用户名为空"),
("test", "123", 1003, "用户不存在"),
]
@pytest.mark.parametrize("username,password,expected_code,description", test_data)
def test_login(username, password, expected_code, description):
"""登录接口测试"""
url = "https://api.example.com/api/v1/login"
data = {
"username": username,
"password": password
}
response = requests.post(url, json=data)
result = response.json()
assert result["code"] == expected_code, f"{description} 失败"
从文件读取数据
python
import csv
import pytest
import requests
def read_csv_data(file_path):
"""从CSV读取测试数据"""
data = []
with open(file_path, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
data.append((
row['username'],
row['password'],
int(row['expectedCode']),
row['description']
))
return data
# 读取数据
test_data = read_csv_data('login_data.csv')
@pytest.mark.parametrize("username,password,expected_code,description", test_data)
def test_login_from_csv(username, password, expected_code, description):
"""从CSV数据驱动登录测试"""
url = "https://api.example.com/api/v1/login"
response = requests.post(url, json={
"username": username,
"password": password
})
assert response.json()["code"] == expected_code
从JSON读取数据
python
import json
import pytest
def read_json_data(file_path):
"""从JSON读取测试数据"""
with open(file_path, 'r', encoding='utf-8') as f:
return json.load(f)
# JSON数据文件
test_data = read_json_data('login_data.json')
@pytest.mark.parametrize("case", test_data)
def test_login_json(case):
"""从JSON数据驱动测试"""
response = requests.post(url, json=case['input'])
assert response.json()["code"] == case['expected']['code']
login_data.json:
json
[
{
"input": {"username": "admin", "password": "123456"},
"expected": {"code": 0, "message": "登录成功"},
"description": "正常登录"
},
{
"input": {"username": "admin", "password": "wrong"},
"expected": {"code": 1001, "message": "密码错误"},
"description": "密码错误"
}
]
11.7 数据驱动最佳实践
数据与逻辑分离原则
#mermaid-svg-uq6jVdrB50Q0bdEx{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uq6jVdrB50Q0bdEx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uq6jVdrB50Q0bdEx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uq6jVdrB50Q0bdEx .error-icon{fill:#552222;}#mermaid-svg-uq6jVdrB50Q0bdEx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uq6jVdrB50Q0bdEx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uq6jVdrB50Q0bdEx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uq6jVdrB50Q0bdEx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uq6jVdrB50Q0bdEx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uq6jVdrB50Q0bdEx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uq6jVdrB50Q0bdEx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uq6jVdrB50Q0bdEx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uq6jVdrB50Q0bdEx .marker.cross{stroke:#333333;}#mermaid-svg-uq6jVdrB50Q0bdEx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uq6jVdrB50Q0bdEx p{margin:0;}#mermaid-svg-uq6jVdrB50Q0bdEx .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uq6jVdrB50Q0bdEx .cluster-label text{fill:#333;}#mermaid-svg-uq6jVdrB50Q0bdEx .cluster-label span{color:#333;}#mermaid-svg-uq6jVdrB50Q0bdEx .cluster-label span p{background-color:transparent;}#mermaid-svg-uq6jVdrB50Q0bdEx .label text,#mermaid-svg-uq6jVdrB50Q0bdEx span{fill:#333;color:#333;}#mermaid-svg-uq6jVdrB50Q0bdEx .node rect,#mermaid-svg-uq6jVdrB50Q0bdEx .node circle,#mermaid-svg-uq6jVdrB50Q0bdEx .node ellipse,#mermaid-svg-uq6jVdrB50Q0bdEx .node polygon,#mermaid-svg-uq6jVdrB50Q0bdEx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uq6jVdrB50Q0bdEx .rough-node .label text,#mermaid-svg-uq6jVdrB50Q0bdEx .node .label text,#mermaid-svg-uq6jVdrB50Q0bdEx .image-shape .label,#mermaid-svg-uq6jVdrB50Q0bdEx .icon-shape .label{text-anchor:middle;}#mermaid-svg-uq6jVdrB50Q0bdEx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uq6jVdrB50Q0bdEx .rough-node .label,#mermaid-svg-uq6jVdrB50Q0bdEx .node .label,#mermaid-svg-uq6jVdrB50Q0bdEx .image-shape .label,#mermaid-svg-uq6jVdrB50Q0bdEx .icon-shape .label{text-align:center;}#mermaid-svg-uq6jVdrB50Q0bdEx .node.clickable{cursor:pointer;}#mermaid-svg-uq6jVdrB50Q0bdEx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uq6jVdrB50Q0bdEx .arrowheadPath{fill:#333333;}#mermaid-svg-uq6jVdrB50Q0bdEx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uq6jVdrB50Q0bdEx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uq6jVdrB50Q0bdEx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uq6jVdrB50Q0bdEx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uq6jVdrB50Q0bdEx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uq6jVdrB50Q0bdEx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uq6jVdrB50Q0bdEx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uq6jVdrB50Q0bdEx .cluster text{fill:#333;}#mermaid-svg-uq6jVdrB50Q0bdEx .cluster span{color:#333;}#mermaid-svg-uq6jVdrB50Q0bdEx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uq6jVdrB50Q0bdEx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uq6jVdrB50Q0bdEx rect.text{fill:none;stroke-width:0;}#mermaid-svg-uq6jVdrB50Q0bdEx .icon-shape,#mermaid-svg-uq6jVdrB50Q0bdEx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uq6jVdrB50Q0bdEx .icon-shape p,#mermaid-svg-uq6jVdrB50Q0bdEx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uq6jVdrB50Q0bdEx .icon-shape .label rect,#mermaid-svg-uq6jVdrB50Q0bdEx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uq6jVdrB50Q0bdEx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uq6jVdrB50Q0bdEx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uq6jVdrB50Q0bdEx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 测试用例代码
测试数据文件
测试逻辑
CSV/JSON/Excel
Python/Java代码
数据管理建议
| 建议 | 说明 |
|---|---|
| 数据独立 | 每个测试用例的数据互不依赖 |
| 数据清理 | 测试后清理产生的数据 |
| 数据版本 | 测试数据纳入版本控制 |
| 敏感信息 | 密码等敏感信息使用环境变量 |
| 数据描述 | 每条数据都有清晰的描述 |
数据文件模板
CSV模板:
csv
case_id,description,method,url,headers,body,expected_status,expected_field,expected_value
LOGIN-001,正常登录,POST,/api/v1/login,,"{""username"":""admin"",""password"":""123456""}",200,code,0
LOGIN-002,密码错误,POST,/api/v1/login,,"{""username"":""admin"",""password"":""wrong""}",401,code,1001
11.8 本章小结
数据驱动核心
#mermaid-svg-iLNBdHFjzTblnYPk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iLNBdHFjzTblnYPk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iLNBdHFjzTblnYPk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iLNBdHFjzTblnYPk .error-icon{fill:#552222;}#mermaid-svg-iLNBdHFjzTblnYPk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iLNBdHFjzTblnYPk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iLNBdHFjzTblnYPk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iLNBdHFjzTblnYPk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iLNBdHFjzTblnYPk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iLNBdHFjzTblnYPk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iLNBdHFjzTblnYPk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iLNBdHFjzTblnYPk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iLNBdHFjzTblnYPk .marker.cross{stroke:#333333;}#mermaid-svg-iLNBdHFjzTblnYPk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iLNBdHFjzTblnYPk p{margin:0;}#mermaid-svg-iLNBdHFjzTblnYPk .edge{stroke-width:3;}#mermaid-svg-iLNBdHFjzTblnYPk .section--1 rect,#mermaid-svg-iLNBdHFjzTblnYPk .section--1 path,#mermaid-svg-iLNBdHFjzTblnYPk .section--1 circle,#mermaid-svg-iLNBdHFjzTblnYPk .section--1 polygon,#mermaid-svg-iLNBdHFjzTblnYPk .section--1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .section--1 text{fill:#ffffff;}#mermaid-svg-iLNBdHFjzTblnYPk .node-icon--1{font-size:40px;color:#ffffff;}#mermaid-svg-iLNBdHFjzTblnYPk .section-edge--1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .edge-depth--1{stroke-width:17;}#mermaid-svg-iLNBdHFjzTblnYPk .section--1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled,#mermaid-svg-iLNBdHFjzTblnYPk .disabled circle,#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:lightgray;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:#efefef;}#mermaid-svg-iLNBdHFjzTblnYPk .section-0 rect,#mermaid-svg-iLNBdHFjzTblnYPk .section-0 path,#mermaid-svg-iLNBdHFjzTblnYPk .section-0 circle,#mermaid-svg-iLNBdHFjzTblnYPk .section-0 polygon,#mermaid-svg-iLNBdHFjzTblnYPk .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-iLNBdHFjzTblnYPk .section-0 text{fill:black;}#mermaid-svg-iLNBdHFjzTblnYPk .node-icon-0{font-size:40px;color:black;}#mermaid-svg-iLNBdHFjzTblnYPk .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-iLNBdHFjzTblnYPk .edge-depth-0{stroke-width:14;}#mermaid-svg-iLNBdHFjzTblnYPk .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled,#mermaid-svg-iLNBdHFjzTblnYPk .disabled circle,#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:lightgray;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:#efefef;}#mermaid-svg-iLNBdHFjzTblnYPk .section-1 rect,#mermaid-svg-iLNBdHFjzTblnYPk .section-1 path,#mermaid-svg-iLNBdHFjzTblnYPk .section-1 circle,#mermaid-svg-iLNBdHFjzTblnYPk .section-1 polygon,#mermaid-svg-iLNBdHFjzTblnYPk .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .section-1 text{fill:black;}#mermaid-svg-iLNBdHFjzTblnYPk .node-icon-1{font-size:40px;color:black;}#mermaid-svg-iLNBdHFjzTblnYPk .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .edge-depth-1{stroke-width:11;}#mermaid-svg-iLNBdHFjzTblnYPk .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled,#mermaid-svg-iLNBdHFjzTblnYPk .disabled circle,#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:lightgray;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:#efefef;}#mermaid-svg-iLNBdHFjzTblnYPk .section-2 rect,#mermaid-svg-iLNBdHFjzTblnYPk .section-2 path,#mermaid-svg-iLNBdHFjzTblnYPk .section-2 circle,#mermaid-svg-iLNBdHFjzTblnYPk .section-2 polygon,#mermaid-svg-iLNBdHFjzTblnYPk .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .section-2 text{fill:#ffffff;}#mermaid-svg-iLNBdHFjzTblnYPk .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-iLNBdHFjzTblnYPk .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .edge-depth-2{stroke-width:8;}#mermaid-svg-iLNBdHFjzTblnYPk .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled,#mermaid-svg-iLNBdHFjzTblnYPk .disabled circle,#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:lightgray;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:#efefef;}#mermaid-svg-iLNBdHFjzTblnYPk .section-3 rect,#mermaid-svg-iLNBdHFjzTblnYPk .section-3 path,#mermaid-svg-iLNBdHFjzTblnYPk .section-3 circle,#mermaid-svg-iLNBdHFjzTblnYPk .section-3 polygon,#mermaid-svg-iLNBdHFjzTblnYPk .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .section-3 text{fill:black;}#mermaid-svg-iLNBdHFjzTblnYPk .node-icon-3{font-size:40px;color:black;}#mermaid-svg-iLNBdHFjzTblnYPk .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .edge-depth-3{stroke-width:5;}#mermaid-svg-iLNBdHFjzTblnYPk .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled,#mermaid-svg-iLNBdHFjzTblnYPk .disabled circle,#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:lightgray;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:#efefef;}#mermaid-svg-iLNBdHFjzTblnYPk .section-4 rect,#mermaid-svg-iLNBdHFjzTblnYPk .section-4 path,#mermaid-svg-iLNBdHFjzTblnYPk .section-4 circle,#mermaid-svg-iLNBdHFjzTblnYPk .section-4 polygon,#mermaid-svg-iLNBdHFjzTblnYPk .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .section-4 text{fill:black;}#mermaid-svg-iLNBdHFjzTblnYPk .node-icon-4{font-size:40px;color:black;}#mermaid-svg-iLNBdHFjzTblnYPk .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .edge-depth-4{stroke-width:2;}#mermaid-svg-iLNBdHFjzTblnYPk .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled,#mermaid-svg-iLNBdHFjzTblnYPk .disabled circle,#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:lightgray;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:#efefef;}#mermaid-svg-iLNBdHFjzTblnYPk .section-5 rect,#mermaid-svg-iLNBdHFjzTblnYPk .section-5 path,#mermaid-svg-iLNBdHFjzTblnYPk .section-5 circle,#mermaid-svg-iLNBdHFjzTblnYPk .section-5 polygon,#mermaid-svg-iLNBdHFjzTblnYPk .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .section-5 text{fill:black;}#mermaid-svg-iLNBdHFjzTblnYPk .node-icon-5{font-size:40px;color:black;}#mermaid-svg-iLNBdHFjzTblnYPk .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .edge-depth-5{stroke-width:-1;}#mermaid-svg-iLNBdHFjzTblnYPk .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled,#mermaid-svg-iLNBdHFjzTblnYPk .disabled circle,#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:lightgray;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:#efefef;}#mermaid-svg-iLNBdHFjzTblnYPk .section-6 rect,#mermaid-svg-iLNBdHFjzTblnYPk .section-6 path,#mermaid-svg-iLNBdHFjzTblnYPk .section-6 circle,#mermaid-svg-iLNBdHFjzTblnYPk .section-6 polygon,#mermaid-svg-iLNBdHFjzTblnYPk .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .section-6 text{fill:black;}#mermaid-svg-iLNBdHFjzTblnYPk .node-icon-6{font-size:40px;color:black;}#mermaid-svg-iLNBdHFjzTblnYPk .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .edge-depth-6{stroke-width:-4;}#mermaid-svg-iLNBdHFjzTblnYPk .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled,#mermaid-svg-iLNBdHFjzTblnYPk .disabled circle,#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:lightgray;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:#efefef;}#mermaid-svg-iLNBdHFjzTblnYPk .section-7 rect,#mermaid-svg-iLNBdHFjzTblnYPk .section-7 path,#mermaid-svg-iLNBdHFjzTblnYPk .section-7 circle,#mermaid-svg-iLNBdHFjzTblnYPk .section-7 polygon,#mermaid-svg-iLNBdHFjzTblnYPk .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .section-7 text{fill:black;}#mermaid-svg-iLNBdHFjzTblnYPk .node-icon-7{font-size:40px;color:black;}#mermaid-svg-iLNBdHFjzTblnYPk .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .edge-depth-7{stroke-width:-7;}#mermaid-svg-iLNBdHFjzTblnYPk .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled,#mermaid-svg-iLNBdHFjzTblnYPk .disabled circle,#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:lightgray;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:#efefef;}#mermaid-svg-iLNBdHFjzTblnYPk .section-8 rect,#mermaid-svg-iLNBdHFjzTblnYPk .section-8 path,#mermaid-svg-iLNBdHFjzTblnYPk .section-8 circle,#mermaid-svg-iLNBdHFjzTblnYPk .section-8 polygon,#mermaid-svg-iLNBdHFjzTblnYPk .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .section-8 text{fill:black;}#mermaid-svg-iLNBdHFjzTblnYPk .node-icon-8{font-size:40px;color:black;}#mermaid-svg-iLNBdHFjzTblnYPk .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .edge-depth-8{stroke-width:-10;}#mermaid-svg-iLNBdHFjzTblnYPk .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled,#mermaid-svg-iLNBdHFjzTblnYPk .disabled circle,#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:lightgray;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:#efefef;}#mermaid-svg-iLNBdHFjzTblnYPk .section-9 rect,#mermaid-svg-iLNBdHFjzTblnYPk .section-9 path,#mermaid-svg-iLNBdHFjzTblnYPk .section-9 circle,#mermaid-svg-iLNBdHFjzTblnYPk .section-9 polygon,#mermaid-svg-iLNBdHFjzTblnYPk .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .section-9 text{fill:black;}#mermaid-svg-iLNBdHFjzTblnYPk .node-icon-9{font-size:40px;color:black;}#mermaid-svg-iLNBdHFjzTblnYPk .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .edge-depth-9{stroke-width:-13;}#mermaid-svg-iLNBdHFjzTblnYPk .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled,#mermaid-svg-iLNBdHFjzTblnYPk .disabled circle,#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:lightgray;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:#efefef;}#mermaid-svg-iLNBdHFjzTblnYPk .section-10 rect,#mermaid-svg-iLNBdHFjzTblnYPk .section-10 path,#mermaid-svg-iLNBdHFjzTblnYPk .section-10 circle,#mermaid-svg-iLNBdHFjzTblnYPk .section-10 polygon,#mermaid-svg-iLNBdHFjzTblnYPk .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .section-10 text{fill:black;}#mermaid-svg-iLNBdHFjzTblnYPk .node-icon-10{font-size:40px;color:black;}#mermaid-svg-iLNBdHFjzTblnYPk .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .edge-depth-10{stroke-width:-16;}#mermaid-svg-iLNBdHFjzTblnYPk .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled,#mermaid-svg-iLNBdHFjzTblnYPk .disabled circle,#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:lightgray;}#mermaid-svg-iLNBdHFjzTblnYPk .disabled text{fill:#efefef;}#mermaid-svg-iLNBdHFjzTblnYPk .section-root rect,#mermaid-svg-iLNBdHFjzTblnYPk .section-root path,#mermaid-svg-iLNBdHFjzTblnYPk .section-root circle,#mermaid-svg-iLNBdHFjzTblnYPk .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-iLNBdHFjzTblnYPk .section-root text{fill:#ffffff;}#mermaid-svg-iLNBdHFjzTblnYPk .section-root span{color:#ffffff;}#mermaid-svg-iLNBdHFjzTblnYPk .section-2 span{color:#ffffff;}#mermaid-svg-iLNBdHFjzTblnYPk .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-iLNBdHFjzTblnYPk .edge{fill:none;}#mermaid-svg-iLNBdHFjzTblnYPk .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-iLNBdHFjzTblnYPk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 数据驱动
核心思想
数据与逻辑分离
一套逻辑多套数据
数据源
CSV简单通用
JSON复杂结构
Excel非技术友好
数据库动态获取
实现方式
Postman Runner
JMeter CSV配置
pytest参数化
最佳实践
数据独立
及时清理
版本控制
课后练习 📝
-
实践题:创建一个CSV文件,包含5组登录测试数据,用Postman Collection Runner执行。
-
编程题:用Python + pytest实现从JSON文件读取数据的参数化测试。
11.9 下章预告
下一章我们将学习接口断言与验证,确保返回结果的正确性!
"数据驱动测试的精髓:写一次代码,测万种可能。"