测试场景建模
前置条件:先阅读
../apifox-cli/SKILL.md。若旧总入口与本 skill 的领域规则冲突,以当前 CLI help 和本 skill 为准。涉及单接口 case 时读取../apifox-test-case/SKILL.md,涉及执行/CI/报告边界时读取../apifox-test-automation/SKILL.md。环境和变量命令以当前 CLI help 为准。
具体命令参数以当前 CLI help 为准。创建和更新测试场景时重点处理步骤保存语义、导入/引用边界、变量传递、复杂步骤字段风险和运行验证边界。Agent 维护场景时优先使用导入/引用命令和 get --with-case-detail 回读真实结构,再做局部 update。
何时使用
- 创建或更新测试场景。
- 设计多步骤自动化流程,例如登录 -> 创建资源 -> 查询 -> 断言 -> 清理。
- 编排多种步骤类型、条件分支、循环、等待、脚本、数据库操作或外部程序。
- 处理前置/后置操作、变量引用、变量提取、断言链路。
- 排查场景步骤衔接失败、变量为空、步骤顺序错误、场景创建后前端展示异常。
不应使用
- 单个接口下的测试用例:转
apifox-test-case。 - 只运行已有场景、套件或 CI 命令:转
apifox-test-automation。 - 只查看报告:按当前 CLI help 使用
test-report;执行和报告边界参考apifox-test-automation。 - 只配置环境、变量、数据库连接:按当前 CLI help 使用 environment、variables、database-connection 等命令。
核心边界
| 概念 | CLI 资源 | 说明 |
|---|---|---|
| 接口测试用例 | test-case | 绑定某个 endpoint 的 case,适合单接口验证 |
| 测试场景 | test-scenario | 多步骤流程编排,支持复杂步骤衔接 |
| 测试套件 | test-suite | 场景/用例集合与回归组织 |
| 环境 | environment | 提供 baseUrl、变量、服务配置 |
| 测试数据 | test-data | 场景或 case 的迭代数据来源 |
命令入口
使用当前 CLI help 查询 test-scenario 的参数。import-steps 和 add-ref 未必出现在顶层“可用命令”列表,但各自支持 --help,可用于导入步骤和添加场景引用。
关键事实:test-scenario create 只保存元数据。即使 create payload 里包含 steps,步骤也不会在 create 阶段保存。正确流程是先 create 元数据,再 get --with-case-detail,再用 import-steps、add-ref 或 test-scenario update --file 添加或修改 steps。
常见导入优先使用高层命令,不要手写复杂 HTTP 绑定结构。已验证的入口包括:
apifox test-scenario import-steps <scenarioId> --project <projectId> --source endpoint --ids <endpointIds> --sync manual
apifox test-scenario import-steps <scenarioId> --project <projectId> --source test-case --endpoint <endpointId> --ids <testCaseIds> --sync manual
apifox test-scenario import-steps <scenarioId> --project <projectId> --source test-scenario --from-scenario <sourceScenarioId> --step-ids <stepIds>
apifox test-scenario add-ref <scenarioId> --project <projectId> --scenario <sourceScenarioId>
语义边界:
import-steps是复制/导入为当前场景自己的步骤。add-ref是添加一个引用其它场景的步骤,不复制源场景内部步骤。--sync manual是默认模式,适合导入后补业务参数、变量引用和断言。--sync auto只适用于 endpoint/test-case 来源,表示随源接口定义或单接口用例自动同步;test-scenario来源不支持 auto。- CLI 是非交互式命令,不会缺 ID 时自动列出全量资源;缺 endpoint、case、scenario 或 step ID 时,跟随 agentHints 先 list/get 定位。
简化创建必须给完整必填参数,但这只会创建空场景。除非用户明确要占位场景,否则“创建自动化测试/场景”不能停留在空场景。
场景建模标准流程
- 明确业务目标:验证什么流程、成功条件是什么、失败如何清理。
- 确认 project、branch、environment。
- 列出涉及的 endpoint、case、环境变量、测试数据、数据库连接或脚本。
- 如果在 AI 分支或迭代分支创建场景,只调整场景本身时不需要先 pick 被引用接口或用例;只有要修改被引用接口、单接口用例或源场景本身时,才从主分支或对应来源迭代分支 pick 所需资源到当前分支。
- 如果已有相似场景,先
test-scenario list/get读取作为模板。 - 用自然语言先设计步骤图,再转 JSON,不要边猜字段边写。
- 获取
test-scenario-createschema 创建元数据。 - 创建后
test-scenario get --with-case-detail回读完整结构。 - 导入已有资源时优先用
import-steps或add-ref,不要直接手写复杂绑定字段。 - 导入后再次
test-scenario get --with-case-detail,确认步骤写入且 HTTP case/detail 展开正常。 - 导入 API definition 或 test-case 后,检查 params、headers、body、脚本变量是否只是 schema 示例值;需要业务值时再用
test-scenario update --file补齐。 - 精细编辑时获取
test-scenario-updateschema,基于完整结构添加或修改 steps。 cli-schema validate通过后 update,再test-scenario get --with-case-detail确认steps非空且结构正确。
test-scenario-update schema 已包含步骤、前后置处理器、断言、提取变量和枚举值说明。首次编写 processor 时先看 schema,不要凭经验猜字段名、枚举值或旧格式。
步骤设计最佳实践
设计每个步骤时都写清:
stepName: 这一步做什么
stepType: 使用哪类步骤
input: 请求、脚本、SQL、等待条件或引用变量
output: 提取哪些变量
dependsOn: 依赖哪些上游步骤输出
assertions: 成功条件
onError: 失败后继续、停止或清理
cleanup: 是否需要后置清理
复杂流程建议分层:
准备数据
鉴权/登录
主流程操作
结果查询与断言
副作用校验
清理资源
数据传递和变量引用
- 创建前列出数据来源:环境变量、全局变量、前置步骤请求/响应、迭代数据、脚本输出。
- 步骤间传递数据优先考虑 Apifox 原生“读取前置步骤的运行结果”,例如
{{$.1.response.body.token}}、{{$.2.response.body.data.id}};它只在自动化测试场景中生效,需要运行完整场景,单独运行某个步骤无法取值。 - 同一数据需要多次引用、跨模块复用,或希望命名更稳定时,使用后置操作的提取变量,再用
{{token}}等变量引用。 - 随机后缀、临时标识符、跨步骤生成但不来自响应的数据,适合写入环境变量,例如
pm.environment.set('runSuffix', suffix);。 - 在脚本中使用前置步骤结果时,不要直接写
{{...}};使用pm.variables.get("$.1.response.body.token")。 - 步骤引用依赖步骤 ID/number,插入、删除、重排步骤后必须同步检查
{{$.步骤号...}}是否仍指向正确步骤。 - 不要假设响应路径一定是
body.data.id;先根据真实响应确认路径,例如{{$.2.response.body.id}}、{{$.2.response.body.data.id}}、{{$.2.response.body.data[0].id}}。 - 生成 payload 时必须原样保留
{{...}}占位符,不要转义、拆分或改写,否则运行时无法替换。 - 变量为空时,优先检查是否运行完整场景、步骤 ID、JSONPath、响应结构、步骤执行顺序和环境选择。
- 这些步骤间传递、
{{$.步骤号...}}和forEach规则只适用于test-scenario,不要写入单接口test-case。
列表响应可作为 forEach.parameters.array,循环内用当前元素引用后续字段:
{
"type": "forEach",
"parameters": {
"array": "{{$.1.response.body}}",
"disableOnError": false
}
}
循环子步骤中引用当前元素:{{$.2.element.id}}。如果默认取数组第一个元素,要显式写出索引,例如 {{$.7.response.body.data[0].id}};如果业务要求特定元素,先筛选,不要假设列表顺序稳定。
步骤内容和处理器结构
Apifox CLI 不会自动格式化场景内容,写入什么字符串,客户端就展示什么字符串。写入前先预格式化字符串字段:
- 接口 Body:
requestBody.data。 - 脚本内容:
parameters.data。 - 前置/后置脚本:
preProcessors[].data、postProcessors[].data。
规则:
- JSON Body 仍然写成字符串,不要写成对象。
- 多行内容用
\n写入。 - 预格式化只影响客户端展示可读性,不改变执行语义。
- 处理器使用扁平结构
{ id, type, data, defaultEnable, enable },不要写旧式嵌套{ type, config }。 - 处理器建议带稳定
id,尤其是assertion、extractor、customScript;缺少id可能 validate 通过但运行器或客户端解析异常。 - 提取全局变量时,
data.variableType使用globals;如需指定生效范围,data.shareScope优先使用PROJECT。TEAM是团队范围,可能依赖增值能力,除非用户明确要求团队范围,否则不要默认使用。 - 写入前照常跑
cli-schema validate。 - 通过
import-steps从 API definition 导入的步骤可能只有结构或 schema 示例值;运行前必须回读并按业务场景补齐 params、headers、body、脚本变量等。
示例:
{
"requestBody": {
"type": "application/json",
"data": "{\n \"name\": \"Demo\",\n \"description\": \"Readable in client\"\n}"
},
"postProcessors": [
{
"id": "postProcessors.0.customScript",
"type": "customScript",
"data": "pm.test('返回 ID', function () {\n var body = pm.response.json();\n pm.expect(body.data.id).to.exist;\n});",
"defaultEnable": true,
"enable": true
},
{
"id": "postProcessors.1.extractor",
"type": "extractor",
"data": {
"variableName": "project_pet_name",
"variableType": "globals",
"shareScope": "PROJECT",
"subject": "responseJson",
"expression": "$.name"
},
"defaultEnable": true,
"enable": true
}
]
}
断言和脚本规则
常规校验优先用可视化 assertion,自定义脚本只作为兜底能力。
断言规则:
- 引用接口形成 HTTP 步骤时,优先使用原接口自带的契约测试/响应校验;默认契约通常已覆盖成功状态码,例如 200。
- 已启用接口契约测试时,不要重复添加“HTTP 状态码为 200”这类同义断言;只补充契约外的业务断言。
- 只有没有合适契约校验,或需要验证额外业务字段时,才单独添加
assertion。 - HTTP 状态码、JSON 字段存在/相等、文本包含等常规校验优先用可视化
assertion,不要默认写customScript。 - 可视化断言字段使用当前 schema 枚举:HTTP 状态码用
httpCode,不要用responseCode;JSON 字段用responseJson,不要用responseBody;全文包含用responseText+include;比较符用equal,不要用equals。
{
"type": "assertion",
"data": {
"name": "返回 ID",
"subject": "responseJson",
"comparison": "exists",
"path": "$.data.id",
"value": ""
},
"defaultEnable": true,
"enable": true
}
脚本规则:
- 自定义脚本只用于可视化断言覆盖不了的逻辑,例如复杂数组筛选、条件判断、二次请求、XML 转换或 schema 校验。
- Apifox 脚本运行时通过
pm对象读写变量、访问响应和定义断言;脚本断言使用pm.test(...)包裹。 - 不要在
pm.test外裸调用pm.response.json(),避免空响应或非 JSON 响应导致错误难定位。 - 不要凭经验扩展运行上下文字段。
pm.environment.set("variable_key", "variable_value");
pm.variables.set("variable_key", "variable_value");
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
pm.test("JSON value equals expected", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.value).to.eql(100);
});
前后置和清理规则
- 前置操作适合鉴权、准备数据、生成随机值、初始化数据库状态。
- 后置操作适合清理测试数据、撤销副作用、释放资源。
- 有副作用的场景必须考虑清理步骤,避免污染环境。
- 数据库、外部程序、写入型接口步骤属于高风险操作,执行前确认环境不是生产环境。
常见复杂步骤处理
| 步骤类型 | 建模建议 |
|---|---|
| 接口请求步骤 | 先确认 endpoint/case 或直接请求结构,输出关键响应字段 |
| 条件分支 | 条件表达式必须基于已存在变量或响应字段 |
| 循环/迭代 | 明确最大次数、退出条件和失败策略 |
| 等待/轮询 | 明确等待上限,避免无限等待 |
| 脚本步骤 | 输入输出变量要显式,避免隐式全局副作用 |
| 数据库步骤 | 先确认连接、SQL 只操作测试数据,敏感信息不输出 |
| 清理步骤 | 即使主流程失败,也尽量能执行清理 |
字段风险提醒
- 步骤顺序看
number,不要只看回读数组顺序。 - HTTP 步骤必须带正确接口绑定信息,避免变成孤立请求或客户端展示异常。可用
type: "http"+bindId: <endpointId>+bindType: "API"+syncMode: "SYNC_WITH_API"+httpApiCase.apiDetailId导入接口;后端会生成relatedId。 - 常见 endpoint/test-case/test-scenario 导入不要手写上述复杂绑定结构,优先用
test-scenario import-steps;引用其它场景优先用test-scenario add-ref。 - 复杂业务场景通常需要
syncMode: "MANUAL"承载定制参数、变量引用和断言,仅绑定 API 不等于可用业务场景。 - 容器步骤
group/if/else/loop/forEach/onError必须包含disable=false、parameters、isOpen=true、children=[]。 - 子步骤放在
children,不要平铺。 group展示名写在parameters.name,不是顶层name。if和条件break使用parameters.keyVariable+operator+valueVariable,不要写expression。else和onError的parameters应为空对象{}。loop使用parameters.count,不是times或其他字段。delay使用parameters.timeout,单位毫秒,不是duration。script步骤使用parameters.type="customScript"、parameters.data=<JS code>、enable=true,不要写language/code。customHttp的 URL 字段叫customHttpRequest.path,不是url,且需要完整请求字段。testCaseRef字段是relatedId,不是caseId。relatedId是后端为场景步骤生成的 HTTP case ID,新建步骤时不要从旧场景复制复用。test-scenario get --with-case-detail用于确认步骤树和 HTTP case/detail 内部配置,例如 Body、Header、postProcessors;如果用户明确要求验证可运行性,再执行运行验证并检查报告。onError目前存在 CLI/schema/get 成功但客户端展开和配置展示不稳定的风险;涉及 onError 时不能仅凭 validate/get 成功判断可用,需要客户端确认。
验证和调试规则
cli-schema validate只保证基础 JSON 结构,不保证 runner、客户端或处理器一定能正确解析。- 更新或导入后先
test-scenario get --with-case-detail确认步骤树非空且结构正确,但不要把 get 成功当成可运行。 - 创建、更新或导入步骤后默认先回读确认,不要自动运行;只有用户明确要求运行、调试失败或交付前需要验证可运行性时,才执行
test-scenario run并检查报告。 - 运行失败时看报告步骤详情,区分失败发生在请求、前置脚本、后置脚本、断言、变量引用还是环境。
- 调试复杂场景时不要反复覆盖同一个业务场景;必要时新建版本化场景,避免旧步骤和新结构混杂。
- 临时删除脚本/断言可以用于定位问题,但不能把“删除功能”当成最终修复。
不可违反规则
- 不要把
test-case的结构直接当作test-scenario步骤结构;导入单接口用例到场景优先使用test-scenario import-steps --source test-case --endpoint <endpointId> --ids <caseIds>。 - 不要只创建一个空场景名;必须包含可展示、可运行的步骤结构。
- 不要误以为 create 能保存 steps;必须 create 元数据后再用
import-steps、add-ref或update --file写入 steps。 - 不要凭经验猜复杂步骤字段;先读 schema 和现有场景模板。
- 不要让后续步骤引用未确认来源的数据;先确认它来自步骤响应、环境变量、迭代数据、extractor 或脚本输出。
- 不要在不确认环境的情况下执行有副作用步骤。
- 更新场景前必须先
get --with-case-detail原结构,避免覆盖整个步骤树。 - 不要反复覆盖同一个复杂业务场景做调试;必要时新建版本化场景,避免旧步骤和新结构混杂。
调试流程
| 现象 | 处理 |
|---|---|
| 场景创建成功但前端步骤不展示 | test-scenario get 看真实保存结构,必要时转 apifox-cli-checkup |
| 后续步骤变量为空 | 检查上游 extractor、响应路径、变量名和执行顺序 |
| 场景 run 失败但单接口成功 | 检查步骤间变量传递、环境、前置脚本和依赖顺序 |
| 循环或等待卡住 | 检查退出条件、最大次数、timeout |
| 清理没执行 | 检查失败策略和后置步骤配置 |
| 报告没有步骤详情 | 先按 apifox-test-automation 区分本地/云端报告,再必要时转 apifox-cli-checkup |






