测试管理

测试用例

测试用例是将多个接口有序地组合在一起运行,用来测试一个完整业务流程。

新建测试用例

路径:自动化测试-测试用例
点击新建测试用例,根据需要新建一个测试用例。
image.png
image.png

导入接口用例

选中某个测试用例,进入编辑页面。
image.png
在测试用例的编辑页面,把鼠标移动到添加步骤上,会展示菜单。
image.png
添加用例有两种方式:从接口导入和从接口用例导入 (推荐)

  • 从【接口】导入:根据接口参数自动生成一个用例,其参数值为空,需要手动填写。
  • 从【接口用例】导入:有两种模式复制和绑定。将接口用例以复制的方式导入,接口用例里的参数也会一同复制过来,和原来用例数据相互独立,各自改动后互不影响。将接口用例以绑定的方式导入,会直接引用原来的用例,两边的改动都会相互实时同步。

    注意

    • 从接口导入后,需要手动设置接口参数,否则运行的时候,接口参数是空的。
    • 从接口用例导入后,会同步导入接口用例里的参数,会方便很多。

从接口用例导入例图
image.png
从接口导入例图
image.png
导入成功后,一定要记得点击保存哦。
image.png

运行测试用例

点击运行,则进入自动化测试。
image.png

测试报告

运行完成后,如图所示,可以看到哪些接口没有通过测试,可以点击对应的接口展开详情;点击更多详情,可以查看该接口的运行结果,方便定位问题。
image.png
image.png
运行结束后可以从下面两个入口,查看之前的测试报告,也可以导出。
image.png

常见问题

B 接口请求参数依赖于 A 接口返回的数据,如何实现?

使用后置脚本和变量(普通变量、环境变量或全局变量)。

  1. A 接口的用例里编写后置脚本,将接口请求返回的数据写入变量,示例: ```javascript // 获取 JSON 格式的请求返回数据 var jsonData = pm.response.json();

// 将 jsonData.token 的值写入变量 pm.variables.set(“token”, jsonData.token);

  1. 2. B 接口对应的参数值,设置为对应的变量,如{{token}},即可直接引用前面设置的变量token的值。
  2. <a name="OnzHb"></a>
  3. ## 测试套件
  4. 测试套件为测试用例的集合,每个测试套件包含多个测试用例。<br />**主要用途:**
  5. 1. 实现测试用例的复用。
  6. 1. 业务流程复杂时,可避免将所有步骤都写在单个用例里,防止造成单个用例里的步骤过多,难以管理。
  7. <a name="uMrLI"></a>
  8. ## 测试数据
  9. 测试用例和测试套件支持测试数据集。当用例或套件运行时,系统会循环运行数据文件里所有的数据集,并且会将数据集里的数据赋值给对应的变量。
  10. 1. 每个数据集可包含多个变量,接口运行时 [使用变量](https://www.apifox.cn/help/app/api-manage/variables/) 的地方会读取对应的值(变量优先级:临时变量 > 测试数据变量 > 环境变量 > 全局变量)。
  11. 1. 可创建多个数据集,系统会遍历运行所有的数据集(每个数据集都会被运行一次)。
  12. 1. 数据集云端同步,成员之间共享测试数据。
  13. 1. 可根据不同环境设置不同的数据集。
  14. <a name="WSWXU"></a>
  15. ### 编辑测试数据
  16. 打开测试用例或测试套件详情页就可以看到测试数据页。通过添加数据集、批量编辑、添加变量等直接编辑测试数据;点击导入可以导入本地csv文件的数据。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/26803611/1653150195048-37b51d44-0b9c-41c4-aef6-613d7dc4e3ff.png#clientId=ue424eaa9-6977-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ua63fe637&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1600&originWidth=2560&originalType=url&ratio=1&rotation=0&showTitle=false&size=460425&status=done&style=none&taskId=ueacd73fd-9190-4377-b489-a6957b01336&title=)
  17. <a name="BzvwH"></a>
  18. ### 使用测试数据
  19. 测试步骤导入的接口或用例,通过引用变量的方式获取测试数据。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/26803611/1653150194967-3f1d2e97-c11c-4f8e-9da2-3f68e199aff9.png#clientId=ue424eaa9-6977-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ud16e387a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=778&originWidth=1816&originalType=url&ratio=1&rotation=0&showTitle=false&size=163132&status=done&style=none&taskId=u0604175c-80a9-4f42-a1ba-0560b852ae9&title=) ![image.png](https://cdn.nlark.com/yuque/0/2022/png/26803611/1653150194940-318c55f2-77f4-4238-b03b-2b4442ffd2b3.png#clientId=ue424eaa9-6977-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u8604b143&margin=%5Bobject%20Object%5D&name=image.png&originHeight=794&originWidth=1816&originalType=url&ratio=1&rotation=0&showTitle=false&size=150901&status=done&style=none&taskId=u0593af2f-58c8-42d4-b92a-5d17b0bd102&title=)
  20. <a name="w6dGV"></a>
  21. ### 运行测试数据
  22. 在运行前需要打开测试数据的开关,再点击运行<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/26803611/1653150195110-522b984d-8526-4f92-b51f-75b6359fe247.png#clientId=ue424eaa9-6977-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u6127847c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1600&originWidth=2560&originalType=url&ratio=1&rotation=0&showTitle=false&size=468245&status=done&style=none&taskId=u5108cb6f-c8ac-497e-a714-27a62f7285e&title=)
  23. <a name="TzcUi"></a>
  24. ### 常见问题
  25. <a name="Rg2c6"></a>
  26. #### 1. 中文导入后乱码的问题
  27. 是因为 windows 默认导出 csv GBK,并且旧版本的 Excel 2016 前会不保存 Bom (byte order mark)。
  28. - Windows 可以使用记事本打开 csv 文件后另存为 utf-8 格式。
  29. - Mac 上可以使用 iconv -f GBK -t UTF-8 xxx.csv > utf-8.csv
  30. <a name="O20Bt"></a>
  31. ## 性能测试
  32. 性能测试有 3 种方式。
  33. <a name="dCnku"></a>
  34. ### 一、Apifox 应用内测试
  35. 运行测试用例的时候,设置线程数大于1即可实现性能测试。<br />线程数即同时【并发】运行的线程数,每个线程都会按顺序运行选中的所有步骤。
  36. > **注意**
  37. > 1. 该功能为 beta 阶段,还在优化中,高并发测试建议导出 JMeter 文件的方式来测试。
  38. <a name="l1l1L"></a>
  39. ### 二、Apifox CLI 方式测试
  40. Apifox CLI Apifox 的命令行运行工具,主要用来做持续集成和压力测试,其压力测试功能目前正在开发中,敬请期待!
  41. <a name="N1il4"></a>
  42. ### 三、导出 JMeter 测试
  43. 测试用例和测试套件可以导出JMeter格式数据,然后可以导入 JMeter 做性能测试。
  44. <a name="PneuZ"></a>
  45. ## 对比测试 (todo)
  46. 相同的接口和参数在两个不同环境下运行,对比其返回的数据差异。
  47. > **注意**
  48. > 该功能还未上线,敬请期待...
  49. <a name="cIJVi"></a>
  50. ### 使用场景
  51. 后端系统重构(或架构升级)时,对比新代码环境和旧代码环境接口返回的数据是否完全一致,用以确保系统重构没有没有带来接口问题。
  52. ---
  53. <a name="X4scQ"></a>
  54. # 持续集成
  55. Apifox 的测试用例和测试套件支持导出Apifox CLIPostmanJmeter 格式数据做持续集成。
  56. <a name="rL0Kb"></a>
  57. ## 一、Apifox CLI 方式
  58. Apifox CLI [Apifox](https://www.apifox.cn/) 的命令行运行工具,主要用来做持续集成。 Apifox 支持实时运行在线数据和导出数据运行2 种方式。
  59. > **注意**
  60. > - Apifox 版本号大于等于 1.0.25 才支持导出Apifox CLI格式数据。
  61. > - Apifox 版本号大于等于 1.4.3 才支持直接实时运行在线数据。
  62. <a name="VC21m"></a>
  63. ### 安装 Apifox CLI
  64. 使用以下命令安装 Apifox CLI
  65. ```latex
  66. npm install -g apifox-cli

实时运行在线数据

在 Apifox 的测试用例和测试套件选择持续集成,生成如下命令
image.png
点击即复制命令,运行即可

apifox run http://xxx/api/v1/api-test/ci-config/xxxx/detail?token=xxxx -r html,cli

导出数据运行

在 Apifox 的测试用例和测试套件导出Apifox CLI格式数据
image.png
运行以下命令

apifox run examples/sample.apifox-cli.json -r cli,html

测试报告

运行完成后测试报告会保存在当前目录下的apifox-reports目录里。
查看Apifox CLI 使用说明

二、Newman 方式(Postman)

使用参考教程:Web API 持续集成:PostMan+Newman+Jenkins(图文讲解)

三、JMeter 方式

导出 JMeter 数据主要用来做性能测试,不过也可以做持续集成,参考教程:性能测试与持续集成(JMeter+Jenkins)

注意 由于 JMeter 不支持 JS 脚本,所以 Apifox 导出 JMeter 数据不包含前置/后置脚本。 后续 Apifox 会将接口返回数据提取和断言功能做成界面配置,这样就可以做到导出数据和 JMeter 兼容了。


Apifox CLI

Apifox CLI 命令行运行

Apifox CLI 主要用来以命令行方式运行 Apifox 的 测试用例或测试套件。

开始

Apifox CLI 依赖于 Node.js >= v10。使用前请先安装 Node.js.

安装

使用以下命令安装 Apifox CLI
$ npm install -g apifox-cli

实时运行在线数据

在 Apifox 的测试用例和测试套件选择持续集成,生成如下命令
image.png
点击即复制命令,运行即可
apifox run http://xxx/api/v1/api-test/ci-config/xxxx/detail?token=xxxx -r html,cli

运行测试用例或测试套件

$ apifox run examples/sample.apifox-cli.json -r cli,html,json
运行完成后测试报告会保存在当前目录下的 apifox-reports 目录里。

  • 如果想要自定义报告,可以通过 json 文件的结果集来定制自己想要的报告

    结合 Jenkins 做持续集成

    Jenkins 配置 NodeJS 环境
    打开 Jenkins,安装 NodeJS 插件 image.png 在全局工具配置中设置 NodeJS 路径 image.png 任务 build 环境中设置 node image.png Jenkins 新建一个任务,添加构建步骤- Excute shell,将 ApifoxCli 的命令拷贝进去,保存并运行即可。 image.png
    Jenkins 报告展示
    在命令中指定生成报告名 ${JOBNAME}${BUILDNUMBER}( Jenkins 内置变量),结合HTML Publisher 插件方便展示报告
    apifox run https://api.apifox.cn/api/v1/api-test/ci-config/XXX/detail?token=xxxxx -r html,cli —out-file ${JOB_NAME}
    ${BUILD_NUMBER}
    image.png

    CLI 如何实现文件参数传递

  1. 首先要回到 接口文档-修改文档 的请求参数处,通过批量编辑,把上传文件的路径改为变量。

image.png
image.png

  1. 保存为接口用例后,再在 自动化测试 中导入 接口/接口用例 。
  2. 最后,去对应的应用中(比如 jenkins)运行时,修改这个路径变量的实际值。

    命令选项

    apifox [options]

  • -h, —help
    使用帮助
  • -v, —version
    显示版本号

    apifox run [options]

    file-source 为从 Apifox 导出的测试用例或测试套件数据文件存放路径。
    更多选项:

    -r, --reporters [reporters] 指定测试报告类型, 支持 cli,html,json (default: ["cli"]) -n, --iteration-count 设置循环次数 -d, --iteration-data 设置用例循环额数据 (JSON 或 CSV) --external-program-path 指定 [外部程序] 的所处文件路径,默认值为命令当前执行目录 --out-dir 输出测试报告目录,默认为当前目录下的 ./apifox-reports --out-file 输出测试报告文件名,不需要添加后缀,默认格式为 apifox-report-{当前时间戳}-0 --database-connection 指定 [数据库配置] 的所处文件路径,使用 URL 测试的时候必须指定 --ignore-redirects 阻止 Apifox 自动重定向返回 3XX 状态码的请求 --silent 阻止 Apifox CLI 输出到控制台 --color 开启/关闭控制台彩色输出 (auto|on|off) (default: "auto") --delay-request [n] 指定请求之间停顿间隔 (default: 0) --timeout-request [n] 指定接口请求超时时间 (default: 0) --timeout-script [n] 指定脚本预执行/后执行接口运行超时时间 (default: 0) -k, --insecure 关闭 SSL 校验 --ssl-client-cert-list 指定客户端证书配置路径 (JSON) --ssl-client-cert 指定客户端证书路径 (PEM) --ssl-client-key 指定客户端证书私钥路径 --ssl-client-passphrase 指定客户端证书密码 (for protected key) --ssl-extra-ca-certs 指定额外受信任的 CA 证书 (PEM) --verbose 显示所有接口请求的详细信息 -h, --help display help for command

    SSL

    客户端证书

    Apifox CLI 支持传入客户端证书

    使用单个 SSL 客户端证书
  • —ssl-client-cert
    公共客户端证书文件的路径

  • —ssl-client-key
    私有客户端密钥的路径(可选)
  • —ssl-client-passphrase
    用于保护私有客户端密钥的密码(可选)

    使用 SSL 客户端证书 配置文件(支持多个证书)
  • —ssl-client-cert-list
    SSL 客户端证书列表配置文件的路径(JSON 格式)。示例如下 ssl-client-cert-list.json ```json ssl-client-cert-list.json

[ { “name”: “domain1”, “matches”: [“https://test.domain1.com/*“, “https://www.domain1/*“], “key”: {“src”: “./client.domain1.key”}, “cert”: {“src”: “./client.domain1.crt”}, “passphrase”: “changeme” }, { “name”: “domain2”, “matches”: [“https://domain2.com/*“], “key”: {“src”: “./client.domain2.key”}, “cert”: {“src”: “./client.domain2.crt”}, “passphrase”: “changeme” } ]

  1. 此选项允许根据 URL 或主机名设置不同的 SSL 客户端证书。 此选项优先于 --ssl-client-cert, --ssl-client-key --ssl-client-passphrase 选项。如果列表中的 URL 没有匹配项,这些选项将用作后备选项。
  2. <a name="fa5rD"></a>
  3. ### 升级版本
  4. 使用以下命令升级 Apifox CLI<br />$ npm install apifox-cli@latest -g
  5. ---
  6. <a name="XHOZY"></a>
  7. # Apifox API
  8. <a name="Nampr"></a>
  9. ## Apifox 开放 API (todo)
  10. 开发者可通过开放 API 读取、修改自己 [Apifox](https://www.apifox.cn/) 账号下的数据。
  11. > **注意**
  12. > 该功能还未上线,敬请期待...
  13. ---
  14. <a name="gg9ax"></a>
  15. # Web 版
  16. <a name="px8aZ"></a>
  17. ## 浏览器扩展
  18. Apifox 浏览器扩展用于 Web 版接口调试,须使用 Chrome 浏览器,暂只能使用本地安装的方式。
  19. > **下载地址**
  20. > [下载地址](https://apifox-generic.pkg.coding.net/apifox/apifox-desktop/Apifox-browser-extension.zip)
  21. <a name="oWAlz"></a>
  22. ### 安装方法
  23. 1. 扩展 zip 后解压
  24. 1. 浏览器打开 chrome://extensions
  25. > 必须开启开发者模式
  26. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/26803611/1653200583068-45dd81c0-dad8-4a92-b20a-c98d97f41110.png#clientId=u22741251-f7dd-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u2d584693&margin=%5Bobject%20Object%5D&name=image.png&originHeight=884&originWidth=1000&originalType=url&ratio=1&rotation=0&showTitle=false&size=127415&status=done&style=none&taskId=ubcebde39-a14e-4974-a2db-7b0563f4123&title=)
  27. 3. 然后点击加载已解压的扩展程序,加载后需要刷新访问中的 Apifox Web 网页,Agent 才能生效
  28. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/26803611/1653200583393-b65a17dd-3f9c-4cb2-b2de-38c4f8e3dc9a.png#clientId=u22741251-f7dd-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ue82b9b8e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=884&originWidth=1000&originalType=url&ratio=1&rotation=0&showTitle=false&size=118349&status=done&style=none&taskId=uca0f7e49-84f3-44a9-838b-72644d149be&title=)
  29. 4. 部分浏览器版本,需要手动修改赋予权限,否则会请求失败
  30. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/26803611/1653200583391-cad385b7-090c-41dc-87b7-6cd37e6a3d7e.png#clientId=u22741251-f7dd-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=uef893023&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1888&originWidth=3024&originalType=url&ratio=1&rotation=0&showTitle=false&size=305725&status=done&style=none&taskId=u021e7993-02f6-499e-a610-a45cd41c47e&title=)
  31. <a name="rZAw2"></a>
  32. ### FAQ
  33. 1. 为什么我安装不成功?
  34. 检测是否在 chrome://extensions 开启了开发者模式。
  35. 2. Web 版调试不支持调用数据库、执行本地代码?
  36. 这是浏览器限制,目前版本若需要则建议使用 [桌面版](https://apifox.cn/)。
  37. 3. Web 版调试不支持 gethead 方法请求中带 body
  38. 这是浏览器限制,目前版本调试发起请求会去除 GetHead 方法请求的 body,若需要调试此类型接口建议使用 [桌面版](https://apifox.cn/)。
  39. ---
  40. <a name="sNA3t"></a>
  41. # 插件
  42. <a name="lGvp3"></a>
  43. ## 插件安装、开发 (todo)
  44. > **注意**
  45. > 该功能还未上线,敬请期待...
  46. <a name="S4cIJ"></a>
  47. ## 数据导入插件 (todo)
  48. > **注意**
  49. > 该功能还未上线,敬请期待...
  50. <a name="fcx20"></a>
  51. ## 数据导出插件 (todo)
  52. > **注意**
  53. > 该功能还未上线,敬请期待...
  54. ---
  55. <a name="s7ipt"></a>
  56. # 更多功能
  57. <a name="TAcFB"></a>
  58. ## 快捷键
  59. | 功能 | Windows / Linux | macOS |
  60. | --- | --- | --- |
  61. | 新建接口 | **Ctrl + N** | **⌘ + N** |
  62. | 新建快捷调试 | **Ctrl + T** | **⌘ + T** |
  63. | 保存接口 / 保存用例 | **Ctrl + S** | **⌘ + S** |
  64. | 发送请求 | **Ctrl + Enter** | **⌘ + Enter** |
  65. | 切换到【运行】Tab | **Ctrl + Enter** | **⌘ + Enter** |
  66. | 关闭 Tab | **Ctrl + W** | **⌘ + W** |
  67. | 强制关闭 Tab | **Ctrl + Alt + W** | **⌘ + Option + W** |
  68. | 切换到下一个 Tab | **Ctrl + Tab** Ctrl + PageDown | **⌘ + Option + 向右箭头键** + Shift + ] |
  69. | 切换到上一个 Tab | **Ctrl + Shift + Tab** Ctrl + PageUp | **⌘ + Option + 向左箭头键** + Shift + [ |
  70. | 跳转到特定标签页 | **Ctrl + 1** Ctrl + 8 | **⌘ + 1** + 8 |
  71. | 跳转到最后一个标签页 | **Ctrl + 9** | **⌘ + 9** |
  72. | 导入数据 | **Ctrl + O** | **⌘ + O** |
  73. | 导入抓包数据 (cURL) | **Ctrl + I** | **⌘ + I** |
  74. | 查找接口 | **Ctrl + F** | **Ctrl + F** |
  75. <a name="gQ51w"></a>
  76. ## 私有化部署
  77. 关于 [Apifox](https://www.apifox.cn/) 私有化部署方案及价格,请扫二维码加我们工作人员微信咨询,加微信请备注:私有化+公司名<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/26803611/1653200754139-026962cd-a8ad-498e-9519-3122dda36a5e.png#clientId=uf6587ae1-3da2-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=449&id=u7fef1d82&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1968&originWidth=1500&originalType=url&ratio=1&rotation=0&showTitle=false&size=989795&status=done&style=none&taskId=ue9a69840-f7cd-4079-a02d-7ca7d253c43&title=&width=342)
  78. <a name="aAyTc"></a>
  79. ### 申请攻略
  80. 需要 [Apifox](https://www.apifox.cn/) 功能介绍 PPT 版本的(可用于团队内部分享/推广 Apifox)
  81. ---
  82. <a name="IELJc"></a>
  83. # 参考资料
  84. <a name="reKn2"></a>
  85. ## Apifox Swagger 扩展
  86. <a name="Px5EM"></a>
  87. ### 一、指定某个接口所属目录:x-apifox-folder
  88. 1. 多级目录使用斜杠/分隔。其中\和/为特殊字符,需要转义,\/表示字符/,\\表示字符\。
  89. ```json
  90. "paths": {
  91. "/pets": {
  92. "post": {
  93. ...
  94. "operationId": "addPet",
  95. "x-apifox-folder": "宠物店/宠物信息"
  96. }
  97. }
  98. }

Swagger 注解示例:

  1. @Operation(extensions = {
  2. @Extension(properties = {
  3. @ExtensionProperty(name = "apifox-folder", value = "宠物店/宠物信息")})
  4. })
  5. public Response createPet() {...}

二、接口状态:x-apifox-status

状态 英文
设计中 designing
待确定 pending
开发中 developing
联调中 integrating
测试中 testing
已测完 tested
已发布 released
已废弃 deprecated
有异常 exception
  1. "paths": {
  2. "/pets": {
  3. "post": {
  4. ...
  5. "operationId": "addPet",
  6. "x-apifox-status": "released"
  7. }
  8. }
  9. }

Swagger 注解示例:

  1. @Operation(extensions = {
  2. @Extension(properties = {
  3. @ExtensionProperty(name = "apifox-status", value = "released")})
  4. })
  5. public Response createPet() {...}

JSON Schema 介绍

JSON Schema 规范参考文档:JSON Schema 规范中文版

一、如何描述 JSON ?

JSON (JavaScript Object Notation) 缩写,JSON 是一种数据格式,具有简洁、可读性高、支持广泛的特点。JSON 有以下基本数据类型

  1. // # 1. object
  2. { "key1": "value1", "key2": "value2" }
  3. // # 2. array
  4. [ "first", "second", "third" ]
  5. // # 3. number
  6. 42
  7. // # 4. string
  8. "This is a string"
  9. // # 5. boolean
  10. true
  11. false
  12. // # 6. null
  13. null

在其它语言中也有类似的内建数据类型,但是由于 JavaScript的广泛应用,而 JSON 作 为 JavaScript原生的数据类型,具备更加广泛的支持。
有了上面列举的基本数据类型,JSON 能非常灵活的表示任意复杂的数据结构。举个例子:

  1. {
  2. "name": "George Washington",
  3. "birthday": "February 22, 1732",
  4. "address": "Mount Vernon, Virginia, United States"
  5. }

如何描述上面 JSON 对象呢?
首先,它是一个 object;
其次,它拥有 name、birthday、address 这三个字段
并且,name 、address 的字段值是一个字符串 String,birthday 的值是一个日期。
最后,将上面的信息如何用 JSON 来表示?如下:

  1. {
  2. "type": "object",
  3. "properties": {
  4. "name": { "type": "string" },
  5. "birthday": { "type": "string", "format": "date" },
  6. "address": { "type": "string" }
  7. }
  8. }

这个表示就是一个 JSON SchemaJSON Schema 用于描述 JSON 数据。
相同的数据,可能有不同的表示,比如下面的两种表示,包含的信息量基本是一致的:

  1. // # 1. 表示一
  2. {
  3. "name": "George Washington",
  4. "birthday": "February 22, 1732",
  5. "address": "Mount Vernon, Virginia, United States"
  6. }
  7. // # 2. 表示二
  8. {
  9. "first_name": "George",
  10. "last_name": "Washington",
  11. "birthday": "1732-02-22",
  12. "address": {
  13. "street_address": "3200 Mount Vernon Memorial Highway",
  14. "city": "Mount Vernon",
  15. "state": "Virginia",
  16. "country": "United States"
  17. }
  18. }

在特定的应用场景中,应用程序对数据的结构要求是确定的,出于对数据描述的规范化需 求,需要用 JSON Schema 来规范化。使用 JSON Schema 可以描述 JSON 数据所包含的字 段、以及字段值的类型,以及依赖关系等。
相同信息量的数据,采用不同的形式来表达,用 JSON Schema 来描述也是不一样的,表示二的 JSON Schema 如下:

  1. {
  2. "type": "object",
  3. "properties": {
  4. "first_name": { "type": "string" },
  5. "last_name": { "type": "string" },
  6. "birthday": { "type": "string", "format": "date-time" },
  7. "address": {
  8. "type": "object",
  9. "properties": {
  10. "street_address": { "type": "string" },
  11. "city": { "type": "string" },
  12. "state": { "type": "string" },
  13. "country": { "type" : "string" }
  14. }
  15. }
  16. }
  17. }

从上面的描述,可以很自然的想到 JSON Schema 可以用来做数据校验,比如前后端先把数 据接口约定好,写好 JSON Schema,等后端把接口输出完毕,直接用 JSON Schema 来对接 口做验收。
关于 JSON Schema 的应用,对 JSON Schema 有过了解的人可以直接跳到第三、四部分。
接下来对 JSON Schema 做一些举例说明。

二、JSON Schema 的举例

1. 空 schema

  1. {}

以下都是合法的 JSON

  1. 42
  2. "I'm a string"
  3. [{"an": "aaa","bbb":{"nest":"data"}}]

2. type 指定 JSON 数据类型

  1. { "type": "string" }
  2. "I'm a string"
  3. 42
  4. { "type": "number" }
  5. 42
  6. "42"
  7. type` 的可能取值: `string` 、`number` 、`object`、 `array`、 `boolean`、 `null`

3. type 可以包含多个类型

  1. { "type": ["number", "string"] }
  2. "I'm a string" // 合法
  3. 42 // 合法
  4. ["Life", "the universe", "and everything"] // 不合法

4. string 限定长度

  1. {
  2. "type": "string",
  3. "minLength": 2,
  4. "maxLength": 3
  5. }
  6. "AA" // 合法
  7. "AAA" // 合法
  8. "A" // 不合法
  9. "AAAA" // 不合法

5. string 模式匹配

  1. {
  2. "type": "string",
  3. "pattern": "^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$"
  4. }
  5. "555-1212" // ok
  6. "(888)555-1212" // ok
  7. "(888)555-1212 ext. 532" // not ok
  8. "(800)FLOWERS" // not ok

6. string 值的枚举

  1. {
  2. "type": "string",
  3. "enum": ["red", "amber", "green"]
  4. }
  5. "red" // ok
  6. "blue" // not ok: blue 没有在 enum 枚举项中

7. integer

integer 一定是整数类型的 number

  1. { "type": "integer" }
  2. 42 // ok
  3. 1024 // ok

8. multipleOf 数字倍数

  1. { "type": "number", "multipleOf": 2.0 }
  2. 42 // ok
  3. 21 // not ok

9. number 限定范围

  1. {
  2. "type": "number",
  3. "minimum": 0,
  4. "maximum": 100,
  5. "exclusiveMaximum": true
  6. }

exclusiveMaximum 为 true 表示不包含边界值 maximum,类似的还有 exclusiveMinimum 字段.

10. object 不允许有额外的字段

  1. {
  2. "type": "object",
  3. "properties": {
  4. "number": { "type": "number" },
  5. "street_name": { "type": "string" },
  6. "street_type": {
  7. "type": "string",
  8. "enum": ["Street", "Avenue", "Boulevard"]
  9. }
  10. },
  11. "additionalProperties": false
  12. }
  13. { "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" } // ok
  14. { "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue","direction": "NW" } // not ok

因为包含了额外的字段 direction,而 schema 规定了不允许额外的字段 “additionalProperties”: false

11. object 允许有额外的字段,并限定类型

  1. {
  2. "type": "object",
  3. "properties": {
  4. "number": { "type": "number" },
  5. "street_name": { "type": "string" },
  6. "street_type": {
  7. "type": "string",
  8. "enum": ["Street", "Avenue", "Boulevard"]
  9. }
  10. },
  11. "additionalProperties": { "type": "string" }
  12. }
  13. { "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue","direction": "NW" } // ok
  14. { "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "office_number": 201 } // not ok
  15. 额外字段 `"office_number": 201` number 类型,不符合 schema

12. object 必填字段

  1. {
  2. "type": "object",
  3. "properties": {
  4. "name": { "type": "string" },
  5. "email": { "type": "string" },
  6. "address": { "type": "string" },
  7. "telephone": { "type": "string" }
  8. },
  9. "required": ["name", "email"]
  10. }
  11. // ok
  12. {
  13. "name": "William Shakespeare",
  14. "email": "bill@stratford-upon-avon.co.uk"
  15. }

多出字段也是 ok 的

  1. // ok
  2. {
  3. "name": "William Shakespeare",
  4. "email": "bill@stratford-upon-avon.co.uk",
  5. "address": "Henley Street, Stratford-upon-Avon, Warwickshire, England",
  6. "authorship": "in question"
  7. }

少了字段,就是不行

  1. // not ok
  2. {
  3. "name": "William Shakespeare",
  4. "address": "Henley Street, Stratford-upon-Avon, Warwickshire, England",
  5. }

13. object 指定属性个数

  1. {
  2. "type": "object",
  3. "minProperties": 2,
  4. "maxProperties": 3
  5. }
  6. { "a": 0, "b": 1 } // ok
  7. { "a": 0, "b": 1, "c": 2, "d": 3 } // not ok

14. Dependencies 依赖

  1. 略复杂,不提供示例

15. Object 属性的模式匹配

  1. {
  2. "type": "object",
  3. "patternProperties": {
  4. "^S_": { "type": "string" },
  5. "^I_": { "type": "integer" }
  6. },
  7. "additionalProperties": false
  8. }
  9. { "S_25": "This is a string" } // ok
  10. { "I_0": 42 } // ok
  11. // not ok
  12. { "I_42": "This is a string" }
  13. { "keyword": "value" }

16. array 数组

  1. // ok
  2. { "type": "array" }
  3. [1, 2, 3, 4, 5]
  4. [3, "different", { "types" : "of values" }]
  5. // not ok:
  6. {"Not": "an array"}

17. array 指定数组成员类型

  1. {
  2. "type": "array",
  3. "items": {
  4. "type": "number"
  5. }
  6. }
  7. [1, 2, 3, 4, 5] // ok
  8. [1, 2, "3", 4, 5] // not ok

18. array 指定数组成员类型,逐个指定

  1. {
  2. "type": "array",
  3. "items": [{
  4. "type": "number"
  5. },{
  6. "type": "string"
  7. },{
  8. "type": "string",
  9. "enum": ["Street", "Avenue", "Boulevard"]
  10. },{
  11. "type": "string",
  12. "enum": ["NW", "NE", "SW", "SE"]
  13. }]
  14. }
  15. // ok
  16. [1600, "Pennsylvania", "Avenue", "NW"]
  17. [10, "Downing", "Street"] // 缺失一个也是可以的
  18. [1600, "Pennsylvania", "Avenue", "NW", "Washington"] // 多出一个也是可以的
  19. // not ok
  20. [24, "Sussex", "Drive"]
  21. ["Palais de l'Élysée"]

19. array 指定数组成员类型,逐个指定,严格限定

  1. {
  2. "type": "array",
  3. "items": [{
  4. "type": "number"
  5. },
  6. {
  7. "type": "string"
  8. },
  9. {
  10. "type": "string",
  11. "enum": ["Street", "Avenue", "Boulevard"]
  12. },
  13. {
  14. "type": "string",
  15. "enum": ["NW", "NE", "SW", "SE"]
  16. }
  17. ],
  18. "additionalItems": false
  19. }
  20. [1600, "Pennsylvania", "Avenue", "NW"] // ok
  21. [1600, "Pennsylvania", "Avenue"] // ok
  22. [1600, "Pennsylvania", "Avenue", "NW", "Washington"] // not ok 多出了字段就是不行

20. array 数组长度限制

  1. {
  2. "type": "array",
  3. "minItems": 2,
  4. "maxItems": 3
  5. }
  6. [1, 2] // ok
  7. [1, 2, 3, 4] // not ok

21. array element uniqueness 数组元素的唯一性

  1. {
  2. "type": "array",
  3. "uniqueItems": true
  4. }
  5. [1, 2, 3, 4, 5] // ok
  6. [1, 2, 3, 3, 4] // not ok:出现了重复的元素 3

22. boolean

  1. { "type": "boolean" }
  2. true // ok
  3. 0 // not ok

23. null

  1. { "type": "null" }
  2. null // ok
  3. "" // not ok

24. schema 的合并

string 类型,最大长度为 5 ;或 number 类型,最小值为 0

  1. {
  2. "anyOf": [
  3. { "type": "string", "maxLength": 5 },
  4. { "type": "number", "minimum": 0 }
  5. ]
  6. }
  7. `anyOf` 包含了两条规则,符合任意一条即可
  8. "short" // ok
  9. 42 // ok
  10. "too long" // not ok 长度超过 5
  11. -5 // not ok 小于了 0

25. allOf、oneOf

  1. `anyOf` 是满足任意一个 Schema 即可,而 `allOf` 是要满足所有 Schema
  2. `oneOf` 是满足且只满足一个

26. oneOf

  1. {
  2. "oneOf": [
  3. { "type": "number", "multipleOf": 5 },
  4. { "type": "number", "multipleOf": 3 }
  5. ]
  6. }
  7. 10 // ok
  8. 15 // not ok 因为它既是 3 又是 5 的倍数

上面的 schema 也可以写为:

  1. {
  2. "type": "number",
  3. "oneOf": [
  4. { "multipleOf": 5 },
  5. { "multipleOf": 3 }
  6. ]
  7. }

27. not

  1. { "not": { "type": "string" } }

只要是非 string 类型即可

  1. 42 // ok
  2. {"key" : "value"} // ok
  3. "This is a string" // not ok

JSON Path 介绍

JSONPath 之于 JSON,就如 XPath 之于 XML。JSONPath 可以方便对 JSON 数据结构进行内容提取。

概览

  1. 根对象使用$来表示,而无需区分是对象还是数组。
  2. 表达式可以使用.,也可以使用[]。如:$.store.book[0].title 或 $[‘store’][‘book’][0][‘title’]
  3. 表达式()可用作显式名称或索引的替代,如:$.store.book[(@.length-1)].title 表示获取最后一个 book 的 title。
  4. 使用符号@表示当前对象。过滤器表达式通过语法支持,?()如:$.store.book[?(@.price < 10)].title 表示获取价格小于 10 的所有 book 的 title。

    语法

    要点:
  • $ 表示文档的根元素
  • @ 表示文档的当前元素
  • .node_name 或 [‘node_name’] 匹配下级节点
  • [index] 检索数组中的元素
  • [start:end:step] 支持数组切片语法
    • 作为通配符,匹配所有成员
  • .. 子递归通配符,匹配成员的所有子元素
  • () 使用表达式
  • ?()进行数据筛选

JSONPath 语法和 XPath 对比:

XPath JsonPath 说明
/ $ 文档根元素
. @ 当前元素
/ .或[] 匹配下级元素
.. N/A 匹配上级元素,JsonPath不支持此操作符
// .. 递归匹配所有子元素
* * 通配符,匹配下级元素
@ N/A 匹配属性,JsonPath不支持此操作符
[] [] 下标运算符,根据索引获取元素,XPath索引从1开始,JsonPath索引从0开始
| [,] 连接操作符,将多个结果拼接成数组返回,可以使用索引或别名
N/A [start:end:step] 数据切片操作,XPath不支持
[] ?() 过滤表达式
N/A () 脚本表达式,使用底层脚本引擎,XPath不支持
() N/A 分组,JsonPath不支持

注意:

  • JsonPath 的索引从0开始计数
  • JsonPath 中字符串使用单引号表示,例如:$.store.book[?(@.category==’reference’)]中的’reference’

    JsonPath示例

    下面是相应的JsonPath的示例,代码来源于https://goessner.net/articles/JsonPath/,JSON文档如下:
    1. {
    2. "store": {
    3. "book": [{
    4. "category": "reference",
    5. "author": "Nigel Rees",
    6. "title": "Sayings of the Century",
    7. "price": 8.95
    8. }, {
    9. "category": "fiction",
    10. "author": "Evelyn Waugh",
    11. "title": "Sword of Honour",
    12. "price": 12.99
    13. }, {
    14. "category": "fiction",
    15. "author": "Herman Melville",
    16. "title": "Moby Dick",
    17. "isbn": "0-553-21311-3",
    18. "price": 8.99
    19. }, {
    20. "category": "fiction",
    21. "author": "J. R. R. Tolkien",
    22. "title": "The Lord of the Rings",
    23. "isbn": "0-395-19395-8",
    24. "price": 22.99
    25. }
    26. ],
    27. "bicycle": {
    28. "color": "red",
    29. "price": 19.95
    30. }
    31. }
    32. }
    接下来我们看一下如何对这个文档进行解析:
XPath JsonPath Result
/store/book/author $.store.book[*].author 所有book的author节点
//author $..author 所有author节点
/store/* $.store.* store下的所有节点,book数组和bicycle节点
/store//price $.store..price store下的所有price节点
//book[3] $..book[2] 匹配第3个book节点
//book[last()] $..book[(@.length-1)],或 $..book[-1:] 匹配倒数第1个book节点
//book[position()<3] $..book[0,1],或 $..book[:2] 匹配前两个book节点
//book[isbn] $..book[?(@.isbn)] 过滤含isbn字段的节点
//book[price<10] $..book[?(@.price<10)] 过滤price<10的节点
//* $..* 递归匹配所有子节点

你可以在 http://jsonpath.com/ 站点进行验证JsonPath的执行效果。
参考文档:

  • https://goessner.net/articles/JsonPath/
  • https://www.newtonsoft.com/json/help/html/SelectToken.htm

    XPath 介绍

    XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。

    XML 实例文档

    我们将在下面的例子中使用这个 XML 文档。

    实例

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <bookstore>
    3. <book>
    4. <title lang="eng">Harry Potter</title>
    5. <price>29.99</price>
    6. </book>
    7. <book>
    8. <title lang="eng">Learning XML</title>
    9. <price>39.95</price>
    10. </book>
    11. </bookstore>

    选取节点

    XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。 下面列出了最有用的路径表达式:
表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。

在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:

路径表达式 结果
bookstore 选取 bookstore 元素的所有子节点。
/bookstore 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book 选取属于 bookstore 的子元素的所有 book 元素。
//book 选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//@lang 选取名为 lang 的所有属性。

谓语(Predicates)

谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中。
在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:

路径表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()❤️] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang=’eng’] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]//title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

选取未知节点

XPath 通配符可用来选取未知的 XML 元素。

通配符 描述
* 匹配任何元素节点。
@* 匹配任何属性节点。
node() 匹配任何类型的节点。

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式 结果
/bookstore/* 选取 bookstore 元素的所有子元素。
//* 选取文档中的所有元素。
//title[@*] 选取所有带有属性的 title 元素。

选取若干路径

通过在路径表达式中使用”|”运算符,您可以选取若干个路径。
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式 结果
//book/title | //book/price 选取 book 元素的所有 title 和 price 元素。
//title | //price 选取文档中的所有 title 和 price 元素。
/bookstore/book/title | //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

正则表达式

参考文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions

CSV 格式规范

下面的格式规范定义来源于 RFC 4180,一共七点。

  1. 文件中的各条记录必须位于不同行,其间以换行符 CRLF 分隔。例如: ```latex aaa,bbb,ccc zzz,yyy,xxx
  1. 2. 最后一条记录的末尾可以不包括换行符。例如:
  2. ```latex
  3. aaa,bbb,ccc
  4. zzz,yyy,xxx
  1. 文件中的首条记录可以是字段名(但这不是必要的),且其所含的名称数量及存储规则须与其他记录保持一致。

    field_name,field_name,field_name aaa,bbb,ccc zzz,yyy,xxx

  2. 每条记录中可以包含一个或多个字段,每个字段以半角逗号分隔。文件中的所有记录必须拥有相同数量的字段。字段中的空格属于字段取值,不可忽略。每条记录的最后一个字段之后不应再添加半角逗号。例如:

    aaa,bbb,ccc

  3. 每个字段可以用半角双引号括起来(但这不一定是必要的)。如果字段没有被双引号括起来,那么字段中不应该出现双引号。例如:

    "aaa","bbb","ccc" zzz,yyy,xxx

  4. 含有换行符、半角双引号或半角逗号的字段应该用半角双引号括起来。例如:

    "aaa","b bb","ccc" zzz,yyy,xxx

  5. 如果字段被半角双引号括起来了,那么在表示字段取值中本身含有的半角双引号时,需要在其前方增加一个半角双引号。例如:

    "aaa","b""bb","ccc"

    Socket 粘包和分包问题

    概念

    Socket通信时会对发送的字节数据进行分包和粘包处理,属于一种Socket内部的优化机制。 粘包: 当发送的字节数据包比较小且频繁发送时,Socket内部会将字节数据进行粘包处理,既将频繁发送的小字节数据打包成 一个整包进行发送,降低内存的消耗。 分包: 当发送的字节数据包比较大时,Socket内部会将发送的字节数据进行分包处理,降低内存和性能的消耗。

    例子解释

    当前发送方发送了两个包,两个包的内容如下: 123456789 ABCDEFGH

    我们希望接收方的情况是:收到两个包,第一个包为:123456789,第二个包为:ABCDEFGH。但是在粘包和分包出现的情况就达不到预期情况。

    粘包情况

    两个包在很短的时间间隔内发送,比如在0.1秒内发送了这两个包,如果包长度足够的话,那么接收方只会接收到一个包,如下:

    123456789ABCDEFGH 1

    分包情况

    假设包的长度最长设置为5字节(较极端的假设,一般长度设置为1000到1500之间),那么在没有粘包的情况下,接收方就会收到4个包,如下:

    12345 6789 ABCDE FGH 1234

    处理方式

    因为存在粘包和分包的情况,所以接收方需要对接收的数据进行一定的处理,主要解决的问题有两个:

  6. 在粘包产生时,要可以在同一个包内获取出多个包的内容。

  7. 在分包产生时,要保留上一个包的部分内容,与下一个包的部分内容组合。

目前处理方式主要两种:

一、给数据包的头尾加上标记。

比如在数据包的头部加上“START”字符串,尾部加上”END”字符串,这样可以解析出START和END之间的字符串就是接收方需要接收的内容。(当然真正处理的时候不可能使用START和END这种混效率较高的字符串,此处只是个例子) 上边两个包的例子就可以如下:

START123456789END STARTABCDEFGHEND 12

二、在数据包头部加上内容的长度

发送方在发送的时候就可以在包头加上包的长度,接收方每次接收的时候都根据头部的长度去获取后面的内容。 上边两个包的例子就可以如下:

PACKAGELENGTH:0009123456789 PACKAGELENGTH:0008ABCDEFGH 12

处理例子

头尾标记处理

粘包

START123456789ENDSTARTABCDEFGHEND 1

获取第一个START和第一个END的位置,然后获取他们之间的内容,第二个包的内容就是获取第二个START和第二个END的位置。

分包

START1234567 89END 12

每个包要判断最后是否是END结尾,如果没有找到END,那么就保留上一个包START之后的内容,与下一个包第一个END之前的内容组合。

头部长度处理

粘包

PACKAGELENGTH:0009123456789PACKAGELENGTH:0008ABCDEFGH 1

获取“PACKAGELENGTH:”这个字符串后面4个字符,转化为数字就是包的长度,根据包的长度获取后面的内容,第二个内容的长度就是获取第二个“PACKAGELENGTH:”字符串后面的4个字符。

分包

PACKAGELENGTH:0009123456 789 12

获取“PACKAGELENGTH:”这个字符串后面4个字符,转化为数字就是包的长度,如果包结尾还没有获取完,那么就要获取下一个包前面的部分内容。

部分细节情况

看了前面的例子,比较善于思考的读者肯定已经想到了一些其他问题,这些问题处理起来方式和上面相似,笔者在此罗列一下,就不重复解释了,相信聪明的读者能够自己解决:

1、粘包和分包问题一起出现

START123456789ENDSTARTAB CDEFGHEND 12

2、头尾标志由于分包获取不完整

START123456789E ND

安装 Java 环境

一、 Java 安装包下载地址

Windows 版(64位):https://repo.huaweicloud.com/java/jdk/8u192-b12/jdk-8u192-windows-x64.exe
Windows 版(32位):https://repo.huaweicloud.com/java/jdk/8u192-b12/jdk-8u192-windows-i586.exe
macOS 版:https://repo.huaweicloud.com/java/jdk/8u192-b12/jdk-8u192-macosx-x64.dmg
其他版本:https://repo.huaweicloud.com/java/jdk/8u192-b12/
注意: 上面推荐下载的是 JDK,其实大多数 Windows 电脑安装JRE也能运行,但是也有部分电脑(大多数 Mac 电脑)JRE下无法运行,所以保险起见推荐JDK。
检查 Java 环境是否安装成功:打开命令行,运行java -version,如能正确显示 java 版本号,则表示安装成功。

二、注意点

如果安装后,Apifox 还是没有检查到 java 环境,请尝试以下 2 个方法:

  1. 关掉 Apifox,过一会再重新打开。
  2. 如果上面方法没有解决,请重启电脑,一般重启电脑就既可正常使用。

其他

常见问题

1. Apifox 是否收费?

Apifox 公网版 (SaaS版) 免费,私有化部署版收费。

2. 登录(Auth)态如何实现?

请参考文档:登录态(Auth)如何处理

3. 接口发送请求前需要调用登录接口获取 token 放在 header,如何实现?

请参考文档:登录态(Auth)如何处理

4. B 接口请求参数依赖于 A 接口返回的数据,如何实现?

请参考文档:接口之间如何传递数据

5. 同项目下有不同域名的接口,如何处理?

方案一:在环境里新增多个服务,分别设置不同的前置 URL ,接口分组和接口维度可以指定对应的前置 URL。推荐本方案!
方案二:把域名设置成环境变量如DOMAIN_1,接口路径这样填写:https:///users。接口路径是以http://或https://起始的,系统会自动忽略里环境里前置 URL。
方案三:给不同域名接口设置不同环境,通过切换环境来运行不同域名下的接口。不推荐本方案!

6. 脚本如何读取或修改接口请求信息?

请参考文档:脚本读取/修改接口请求信息

7. 是否支持查询数据库字段作为参数传给接口?

支持,请参考文档:数据库操作

8. 数据是存储在本地还是云端?可否离线使用?可否私有化部署?

目前 Apifox 有 Saas 版 和私有化部署版 。
Saas 版 是免费的,数据都是存在云端的,需要联网才能使用。
私有化部署版 是收费的,数据存在使用者企业内部,不连外网也可以使用。
注意
环境变量/全局变量里的 本地值 仅存放在本地,不会同步到云端,团队成员之间也不会相互同步,适合存放token、账号、密码之类的敏感数据。

9. 使用 Postman 调用接口返回正常,而 Apifox 返回错误

解决方法:对比 postman 和 apifox 实际发出的请求内容(url、参数、body、header)是否完全一样。
查看实际请求内容方法:

  1. Apifox:返回内容下的实际请求 tab 里查看
  2. Postman:点击底部状态栏里的Console查看

    10. 为什么修改了环境变量(或全局变量)值,而引用的地方没有生效?

  3. 请检查环境变量、全局变量、临时变量里是不是有多个地方定义了相同名称的变量,如果有,系统会根据优先级来取值。优先级顺序如下:临时变量>环境变量>全局变量。

  4. 请检查修改的是否是本地值,环境变量(或全局变量)仅读取本地值,而不会读取远程值。

    后续功能规划

    Apifox 后续功能规划主要如下:

  5. 支持接口性能测试(类似 JMeter)

  6. 支持插件市场,可以自己开发插件
  7. 支持更多接口协议,如GraphQL、websocket等
  8. 支持离线使用,项目可选择在线同步(团队协作)还是仅本地存储(单机离线使用)
  9. 提供私有化部署方案

    更新日志

    升级方法:Apifox 软件内“检查更新”,或从官网手动下载。

    Alpha 版说明 Alpha 版为新功能尝鲜版,需要加官方微信群、QQ 群或钉钉群,才能参与 Alpha 版内测。 加群方式:apifox.cn/help/app/contact-us

    1. Apifox 新功能都会先在 Alpha 版上线,等稳定后才会合到正式版。
    2. Alpha 版可能会有一些 bug,如遇到问题及时在群里反馈,我们会第一时间解决。
    3. Alpha 版和正式版数据是互通的。
    4. 已经是 Alpha 版的,直接点击软件内更新。

https://www.apifox.cn/help/app/changelog/