理解和掌握 Apifox 前后置操作——“提取变量”篇

当你开始用 Apifox 做接口测试时,很快就会遇到这样的情况:你需要先调用登录接口获取 token,然后把这个 token 传递给其他接口使用。或者你需要从一个接口的响应中获取某个 ID,然后在其它接口中作为参数使用。
这时候你可能会想,难道每次都要手动复制粘贴吗?当然不是。Apifox 的"提取变量"功能就是为了解决这个问题而存在的。

什么是提取变量
提取变量说白了就是从接口的响应结果中"抠出"你需要的数据,然后把它保存成一个变量,供后面的接口使用。这个过程是自动化的,不需要你手动操作。
比如说,登录接口返回了这样的数据:
{
"code": 200,
"data": {
"token": "eyJhbGciOiJIUzI1NiJ9...",
"userId": 12345
}
}
你可以通过提取变量功能,把 token
和 userId
这两个值分别保存成变量,然后在其他接口中直接使用 {{token}}
和 {{userId}}
来引用它们。
变量的生命周期和作用范围
在 Apifox 中,提取出来的变量并不是都一样的。根据你的需要,它们可以有不同的"生命周期"和"作用范围"。这就涉及到四种不同类型的变量。
临时变量是最短命的。它只在当前这一次接口调用中有效,调用结束就消失了。这种变量适合临时计算一些值,然后在同一个接口的请求中使用。

模块变量的作用范围限定在当前模块(接口分组)内。如果你在"用户管理"模块中提取了一个变量,那么只有"用户管理"模块下的其他接口才能使用它。这种变量适合存储模块内部共享的数据。

环境变量的作用范围是当前环境。当你切换到开发环境时,这些变量就是开发环境的值;切换到测试环境时,就变成测试环境的值。这特别适合存储不同环境下会发生变化的配置信息,比如不同环境的用户 token。

全局变量的作用范围最广,在所有环境、所有模块中都能使用。它适合存储那些在整个项目中都通用的数据。

变量的优先级规则
当你在 Apifox 中使用同名变量时,系统会按照以下优先级顺序来选择使用哪个变量的值:
临时变量 > 环境变量 > 模块变量 > 全局变量
举个具体例子:假设你同时定义了四个名为 userId
的变量:
- 全局变量:
userId = 1000
- 模块变量:
userId = 2000
- 环境变量:
userId = 3000
- 临时变量:
userId = 4000
当你在接口中使用 {{userId}}
时,实际生效的值会是 4000
(临时变量)。
如果没有临时变量,就会使用环境变量的值 3000
;如果环境变量也没有,才会使用模块变量的值 2000
;只有当前面三种都不存在时,才会使用全局变量的值 1000
。
实际操作:如何提取变量
现在我们来看看具体怎么操作。在接口的"后置操作"中,你会看到"提取变量"这个选项。点击添加后,你需要填写几个关键信息。

首先是变量名称。这就是你以后引用这个变量时要用的名字。比如你可以起名为 userToken
或者 currentUserId
。变量名要有意义,让你和团队其他成员能够一眼看出这个变量的用途。
然后选择变量类型。刚才我们说的临时变量、模块变量、环境变量、全局变量,就是在这里选择的。选择哪种类型,主要看你希望这个变量在什么范围内使用。
接下来是提取来源。通常我们选择"Response JSON",因为现在大部分接口都返回 JSON 格式的数据。如果你的接口返回的是 XML,Apifox 也会智能地转换成 JSON 格式来处理。
最关键的是 JSONPath 表达式。这个表达式告诉 Apifox 从响应数据的哪个位置提取值。
JSONPath 表达式的使用
JSONPath 表达式看起来可能有点吓人,但其实很好理解。它就是用来描述 JSON 数据结构中某个位置的"地址"。
比如对于这样的响应数据:
{
"code": 200,
"data": {
"token": "eyJhbGciOiJIUzI1NiJ9...",
"userInfo": {
"id": 12345,
"name": "张三"
}
}
}
如果你要提取 token,JSONPath 表达式就是 $.data.token
。如果要提取用户 ID,就是 $.data.userInfo.id
。
当数据中包含数组时,情况会稍微复杂一点。假设响应是这样的:
{
"data": {
"users": [
{"id": 1, "name": "张三"},
{"id": 2, "name": "李四"}
]
}
}
要提取第一个用户的 ID,表达式就是 $.data.users[0].id
。如果要提取所有用户的 ID,可以用 $.data.users[*].id
。
Apifox 很贴心地提供了"继续提取"选项。当你的 JSONPath 表达式匹配到多个值时(比如一个数组),开启这个选项后,Apifox 会默认提取第一个匹配的值。如果不开启,它会把所有匹配的值作为一个数组来处理。
当然不会 JSONPath 也没关系,需要用到的时候问一下 AI 就行了,把 JSON 丢给 AI 然后让 AI 帮你写,也可以通过 Apfiox 提供的 JSONPath 提取工具快速提取。
除了在后置操作中设置断言,也可以在接口的返回响应中直接设置。

选择合适的变量类型
在实际使用中,选择合适的变量类型非常重要。这不仅影响变量的可用性,也关系到团队协作的效率。
当你在做登录流程测试时,用户的 token 通常应该保存为环境变量。因为在开发环境下,你可能用的是测试账号的 token;在生产环境下,用的可能是另一个账号的 token。这样,当你切换环境时,token 也会自动切换,非常方便。
如果你在测试用户管理模块,需要先创建一个用户,然后在后续的接口中使用这个用户的 ID 进行查询、修改、删除等操作,那么这个用户 ID 就适合保存为模块变量。因为它只在用户管理模块内部使用,不需要暴露给其他模块。
全局变量通常用来存储那些整个项目都会用到的配置信息。比如 API 的版本号、公共的加密密钥等。这些信息一旦设定,在整个项目中都保持一致。
临时变量的使用场景相对较少,主要是在前置脚本中进行一些临时计算(前置操作没有“提取变量”操作),然后在同一个接口请求中使用。比如生成当前时间戳、计算签名等。
提取变量的实战技巧
在实际项目中,你会发现提取变量有一些实用的技巧。
当接口返回的数据结构比较复杂时,你可以先在 Apifox 中发送一次请求,查看返回的数据格式,然后根据实际的数据结构来编写 JSONPath 表达式。这比凭空想象要准确得多。
如果你需要从同一个响应中提取多个变量,不要怕麻烦,就一个一个地添加提取规则。虽然操作多一些,但是这样提取出来的变量更加精确,后续使用也更方便。
在团队协作中,变量的命名规范非常重要。建议使用有意义的前缀,比如用户相关的变量用 user_
开头,订单相关的用 order_
开头。这样团队成员在使用变量时能够快速理解变量的含义。
当你的接口用例涉及多个接口的串联调用时,要特别注意变量的生命周期。确保在需要使用变量的时候,变量确实是有效的。比如,如果你在模块 A 中提取了一个模块变量,就不能在模块 B 中使用它。
调试和验证
提取变量后,你肯定想知道变量是否正确提取了,值是不是你期望的。在 Apifox 中,你可以通过几种方式来验证。
最直接的方法是在接口调用完成后,查看"变量"面板(在右上角的“环境管理”中,以及在模块的“变量”中)。在这里你能看到所有当前可用的变量及其值。如果你发现某个变量的值不对,就需要回头检查 JSONPath 表达式是否写错了。也可以在响应的控制台中查看设置的变量及其值。

另一种验证方法是在后续的接口中使用这些变量。如果变量提取正确,后续接口就能正常工作;如果提取失败或值不对,后续接口就会报错,你能够及时发现问题。
当 JSONPath 表达式比较复杂时,你可以使用一些在线的 JSONPath 测试工具来验证表达式的正确性,或者让 AI 来帮你写。把接口的响应数据粘贴到工具中,然后测试你的表达式能否提取到预期的值。
常见的陷阱和注意事项
在使用提取变量功能时,有几个容易踩的坑需要注意。
首先是空值处理。如果 JSONPath 表达式匹配不到任何数据,变量就会是空的。这可能导致后续接口出错。所以在设计测试用例时,要考虑到接口可能返回空数据的情况。
再一个就是变量覆盖问题。如果你在多个地方提取了同名的变量,后面的会覆盖前面的。这在某些情况下可能不是你想要的结果。解决方法是给变量起不同的名字,或者确保覆盖是你的预期行为。
最后,要注意变量的作用域。不同类型的变量有不同的可见范围,不要试图在错误的地方使用变量。比如在模块 A 中使用模块 B 的模块变量,这是不会成功的。
通过合理使用提取变量功能,你的接口测试会变得更加自动化和高效。不再需要手动复制粘贴数据,整个测试流程可以一气呵成地执行下去。这不仅提高了测试效率,也减少了人为错误的可能性。
掌握了这些基础知识后,你就可以开始在自己的项目中尝试使用提取变量功能了。从简单的 token 提取开始,逐步尝试更复杂的数据提取场景。随着练习的深入,你会发现这个功能在接口测试中的强大作用。
