演示前端

一个用于测试和探索 API 的前端应用程序

您是否曾经参加过“演示”,开发人员自豪地展示了 API 的 JSON 输出屏幕,而用户却感到困惑和分心,无法理解其中的含义?您是否曾经尝试在开发中使用 API,却因难以找到正确的 JSON 负载和标头咒语来测试功能而感到沮丧?演示前端是一个简单的 UI,提供基本功能来演示和探索这样的 API。

2023 年 8 月 23 日


Photo of Matteo Vaccari

Matteo 是 Thoughtworks Italia 的开发人员和技术主管。他喜欢极端编程帮助团队和企业取得成功。


动机

任何运作良好的开发团队的核心实践之一是定期演示他们正在构建的产品的最新改进。如果产品有用户界面,那么演示自然地通过 UI 本身提供,甚至可以让参加会议的利益相关者直接使用它。

但如果产品是 API 呢?通常我们建议后端和前端由同一个团队开发,因为与两个独立的团队必须协调的情况相比,这通常会导致更高的质量和更短的开发时间。但是,在某些情况下,这是不可能的:有时后端(API)是由一家公司开发的,该公司通过该 API 向第三方出售对有用服务的访问权限。例如:金融机构提供“支付网关”API,允许电子商务网站接收来自客户的付款;或者服务提供商通过 API 与价格比较引擎进行交互,价格比较引擎会调用该 API。

在所有 API 没有自然用户界面的情况下,提供有意义的演示变得很困难。有时团队试图通过显示 API 返回的 JSON 代码来演示 API 的使用,但这不容易理解,尤其是对于非技术利益相关者来说。让业务利益相关者使用产品几乎是不可能的。

在这些情况下,我们发现 开发一个简单的 UI,专门用于 API 演示 是有益的。UI 不需要花哨或特别美观,也不需要设置专门的构建;目的是让它轻松地展示 API 使用。

这种演示前端的好处不仅限于在演示期间展示软件;一旦您将其提供,开发人员将使用它在将代码推送到存储库之前在本地机器上测试新功能,而质量分析师、产品负责人和其他利益相关者将使用它在测试环境中测试产品。它还可以用于向可能对购买访问权限感兴趣的潜在合作伙伴演示 API 的使用。演示前端是一个不断给予的礼物。

实用建议

演示前端在 API 可用的所有地方立即可用时效果最佳。例如,在 Spring Boot 应用程序中,您可以将静态 HTML、CSS 和 JavaScript 资产放置在 src/main/resources/public/testdrive 文件夹中,这样就可以通过在例如 https://localhost:8080/testdrive/ 处打开浏览器来访问它们。最简单的演示 UI 只不过是 Postman 的替代品

A screenshot of the simplest possible demo UI,          showing an input text area with an editable input JSON, and an output text area with the          response JSON from the API. The output text area has a green background to signify a successful         response

图 2:用户可以调整请求负载、方法和路径:响应显示在下面的窗口中,以绿色显示以表示成功响应

A screenshot of the same UI, showing an error         response colored in pink, because of a missing parameter

图 3:错误响应通过将输出文本区域着色为粉红色来变得更加明显

演示 UI 为给定的 API 端点准备一个有效的 JSON 请求,然后它允许用户手动修改请求以适合他们想要测试的内容,当用户按下按钮时,它将显示响应,可能还会显示 http 状态代码和任何相关的标头。

即使在这一点上我们仍然将 JSON 显示为输入和输出,但我们比 Postman 有一个很大的优势,因为我们可以使用自动化来增强或修改建议给用户的输入 JSON 的静态版本。例如,如果有效请求应包含唯一标识符,则一小段 JavaScript 代码可以轻松地生成随机标识符,而无需用户进行任何操作。这里关键的是 UI 允许以最小的摩擦进行快速测试。

制作像这样的演示前端所需的 JavaScript 最少:当前的 JavaScript 足够强大,无需特定库,尽管开发人员可能会发现使用轻量级工具(如 htmx、jQuery 甚至内联 React)很方便。我们建议避免设置专门的构建,因为这会在运行 API 和通过 UI 执行测试之间引入额外的步骤。理想情况下,我们唯一想要运行的构建是 API 产品本身的构建。在想要测试某些东西和实际执行测试之间发生的任何延迟都会减慢开发循环。

这种 UI 的自然演变是

  1. 添加生成不同类型输入的功能;也许用适当的 HTML 表单完全替换 JSON 文本区域
  2. 以易于理解的方式解析和显示输出

例如,假设我们有一个与旅行相关的 API,允许我们预订航班,目的是为可以在日期上灵活的旅行者找到最优惠的价格。我们可能有一个初始 API 来执行搜索并返回价格组合列表。输入 JSON 可能看起来像

{
  "departure-airport": "LIN",
  "arrival-airport"  : "FCO",
  "departure-date"   : "2023-09-01",
  "return-date"      : "2023-09-10",
  "adults"           : 1,
  "children"         : 0,
  "infants"          : 0,
  "currency"         : "EUR"
}

我们的演示 UI 将在输入文本区域加载示例负载,从而免除用户记住精确语法的麻烦。

A screenshot of another         demo page, for a fictitious flight search API, with a more complicated         payload

图 4:真实的 JSON 负载往往很复杂

但是,用户可能需要更改日期,因为任何静态的出发或到达日期最终都会失效,因为时间流逝,日期会变成过去,更改日期需要时间,并且可能会由于手动错误而导致更多时间损失。一种解决方案可能是自动修改 JSON 中的日期,将其设置为例如未来 30 天。这将使执行 API 的快速“冒烟测试”变得非常容易:只需单击“搜索航班”并查看结果。

我们可以更进一步:例如,有时我们可能想查看大约六个月后的航班价格;有时是 3 个月,有时只是一周前。提供一个 UI,允许用户通过从下拉菜单中选择来快速更改 JSON 负载,这很酷。如果我们为其他输入字段(例如机场代码)提供相同的功能,我们就不需要用户查找机场代码,这也需要宝贵的时间。

The same page, with a few          dropdown menus that provide an easy way to update the payload

图 5:添加 HTML 表单以自动调整负载

上面的 UI 使更改 JSON 负载变得快速简便,用户只需要很少的专业知识。仍然可以检查生成的 JSON,如果用户想要测试 HTML 表单未涵盖的案例,他们可以直接更改它。

航班搜索 API 可以返回一个按日期变化的价格矩阵,允许客户选择最佳的出发和返回航班组合。例如

The same page, now showing part of a complex         JSON response

图 6:JSON 响应也往往很复杂

人类很难理解 JSON 中的价格矩阵,因此我们可以解析 JSON 并将其格式化为一个漂亮的 HTML 表格。

Again the same page, now with an HTML         table, presenting the JSON response in an easier-to-read way

图 7:解析响应并以易于阅读的格式呈现

一个简单的 HTML 表格可以极大地简化技术和非技术用户验证 API 结果的过程。

常见问题

为什么不使用 Swagger UI 代替呢?

Swagger UI 满足了与演示前端相同的一些优点:它可以立即提供,它在与源代码相同的源代码存储库中定义;它由提供 API 的相同服务提供。与演示前端相比,它确实有一些缺点

  • Swagger UI 中的输入和输出负载仅限于 JSON:您无法使其更具可读性。
  • 它对非技术用户不友好。
  • 它只能提供静态负载;如果您需要在每次调用时提供随机 ID 怎么办?如果负载应包含当前日期怎么办?用户必须手动记住修复负载,并且他们需要知道如何修复它。使用一些 JavaScript,您可以在演示前端轻松地自动提供此功能
  • Swagger UI 不支持工作流;使用演示前端,您可以通过按适当的顺序呈现要进行的调用来引导用户。您还可以从一个调用的输出中获取部分内容,并使用它们来准备工作流中下一个调用的负载

我们是否应该使用 npm 设置专门的构建?

如果您的前端使用专门的构建命令,那么您在本地编辑-编译-运行-测试循环中会多出一个步骤:这会使您的循环变慢。它还需要您使您的持续集成和交付自动化变得复杂:现在您的源代码存储库会生成两个工件而不是一个;您必须构建两者并部署两者。出于这些原因,我不建议这样做。如果您习惯于使用 Angular 等“大型”前端框架,您可能会惊讶于仅通过在内联 <script> 标签中加载 jQueryReact 可以完成多少工作。

我们不是在做客户没有要求的工作吗?

演示前端改进了产品的某些跨职能属性,客户可能会赞赏这些属性:至少,产品的可测试性和开发人员体验,因此开发速度,但还有其他跨职能属性可能会受到有益的影响。

让我告诉你一个故事:有一段时间,我们参与了 API 产品的重写。在该产品中,API 调用可能会导致对其他下游服务的数十次调用,并且这些下游调用中的每一个都可能在 HTTP 意义上失败,通过返回 HTTP 错误状态代码,并且可能在逻辑上失败,通过在响应负载中返回逻辑错误代码。鉴于这些数十个下游调用中的任何一个以不同的方式失败都可能导致我们 API 响应中出现不同的、意外的结果,很明显我们需要一种方法来快速查看我们的系统与下游服务交互时发生了什么,因此我们增强了演示前端,其中包含所有下游服务交互的报告,显示了响应一次对我们 API 的调用时每个下游调用的请求和响应。

演示前端最终成为一个杀手级功能,对产品的成功贡献巨大,因为它允许测试人员轻松地调试为什么调用没有产生预期结果。演示前端最终也提供给了生产环境,以便内部用户可以对来自产品客户端(即他们的合作伙伴)的调用进行故障排除。客户告诉我们,他们很高兴,因为他们现在可以在几分钟内解决调用无法按预期工作的原因,而以前系统需要几天时间才能解决。

客户没有明确要求演示前端,但他们在项目启动时告诉我们,使用他们现有的系统,他们很难调试为什么一些对 API 的调用会返回意外的值。我们为他们构建的演示前端,除了其他功能外,也是他们告诉我们遇到的问题的解决方案。

更进一步

API 端点通常旨在连续使用,以支持某种自动化工作流程,或者可能是人类用户做出的决策过程。在这些情况下,我们可以扩展演示前端以明确支持工作流程。在某种程度上,演示前端可以用作 API 用户如何使用 API 的文档,或者用作完整实现的示例原型前端。

在这个 git 仓库 中有一些示例代码可以用作起点;屏幕截图是从中截取的。


重大修订

2023 年 8 月 23 日:发布