契约测试
契约测试由两部分组成:消费者测试(consumer tests)和提供者测试(provider tests)。消费者和提供者关系的一个简单例子是前端和后端之间的关系。前端是消费者,后端是提供者。前端使用后端提供的 API。测试有助于确保双方遵循约定的契约,任何偏离契约的情况都会触发有意义的对话,以防止破坏性变更被遗漏。
消费者测试类似于单元测试,每个规范(spec)定义一个请求和预期的模拟响应,然后基于这些定义创建契约。提供者测试类似于集成测试 - 每个规范获取契约中定义的请求,在实际服务上运行它,并将响应与契约进行匹配以验证。
您可以在以下位置查看现有的契约测试:
目前,契约本身存储在 /spec/contracts/contracts。计划使用托管在 AWS 或其他类似服务上的 PactBroker。
编写测试
运行消费者测试
在运行消费者测试之前,请进入 spec/contracts/consumer 目录并运行 npm install。要运行所有消费者测试,只需运行 npm run jest:contract -- /specs。否则,要运行特定的规范文件,请将 /specs 替换为特定的规范文件名。运行消费者测试将创建提供者测试用来验证实际 API 行为的契约。
您也可以从项目根目录使用命令 yarn jest:contract 运行测试。
运行提供者测试
在运行提供者测试之前,请确保您的 GDK(GitLab Development Kit)已完全设置并正在运行。您可以遵循 GDK 仓库 中的详细设置说明。要运行提供者测试,您使用可在 ./lib/tasks/contracts 中找到的 Rake 任务。要获取与提供者测试相关的所有 Rake 任务列表,请运行 bundle exec rake -T contracts。例如:
$ bundle exec rake -T contracts
rake contracts:merge_requests:pact:verify:diffs_batch # 验证提供者对 diffs_batch 的消费者契约
rake contracts:merge_requests:pact:verify:diffs_metadata # 验证提供者对 diffs_metadata 的消费者契约
rake contracts:merge_requests:pact:verify:discussions # 验证提供者对 discussions 的消费者契约
rake contracts:merge_requests:test:merge_requests[contract_merge_requests] # 运行所有合并请求契约测试在 Pact Broker 中验证契约
默认情况下,Rake 任务将验证本地存储的契约。为了验证发布在 Pact Broker 中的契约,我们需要将 PACT_BROKER 环境变量设置为 true,并将 QA_PACT_BROKER_HOST 设置为 Pact Broker 的 URL。这里需要指出的是,提供者测试的文件路径和文件名用于在 Pact Broker 中查找契约,因此确保遵循 提供者测试命名约定 非常重要。
将契约发布到 Pact Broker
消费者测试生成的契约可以通过设置 QA_PACT_BROKER_HOST 环境变量并运行 publish-contracts.sh 脚本发布到托管的 Pact Broker。
测试套件文件夹结构和命名约定
为了保持消费者和提供者测试套件的有序和可维护性,测试的组织以及消费者和提供者的一致命名非常重要。因此,遵循以下约定非常重要。
测试套件文件夹结构
为测试套件提供有组织的合理的文件夹结构,使得在审查、调试或引入测试时更容易找到相关文件。
消费者测试
消费者测试根据应用程序中的不同页面进行分组。每个文件包含页面中找到的各种类型的请求。因此,消费者测试文件使用 Rails 标准中如何引用页面的标准进行命名。例如,项目流水线页面将是 Project::Pipelines#index 页面,因此相应的消费者测试将位于 consumer/specs/project/pipelines/index.spec.js。
在定义测试生成的契约的输出位置时,我们希望遵循相同的文件结构,在此示例中为 contracts/project/pipelines/。consumer/resources 和 consumer/fixtures 中也采用这种结构。
文件夹的命名也必须使用复数形式,以匹配 Rails 命名标准中的调用方式。
提供者测试
提供者测试的分组方式类似于我们的控制器。每个测试包含针对 API 端点的各种测试。例如,获取项目流水线列表的 API 端点将位于 provider/pact_helpers/project/pipelines/get_list_project_pipelines_helper.rb。提供者状态根据应用程序中的不同页面进行分组,类似于消费者测试。
命名约定
在编写消费者和提供者测试时,有些部分需要为消费者和提供者指定名称。由于 Pact 对这些名称的命名方式没有限制,因此命名约定很重要,这样在调试时我们可以轻松确定涉及哪些消费者和提供者测试。Pact 还使用消费者和提供者名称以 #{consumer_name}-#{provider_name} 格式创建本地存储的契约文件名。
消费者命名
如文件夹结构部分所述,消费者测试根据应用程序中的不同页面进行分组。因此,消费者名称应遵循使用 Rails 标准的相同命名格式。例如,Project::Pipelines#index 的消费者测试将在 project 文件夹下,并将作为消费者名称称为 Pipelines#index。
提供者命名
这些是为消费者提供数据的 API 端点,因此它们根据所属的 API 端点进行命名。请注意,这以 HTTP 请求方法开头,其余部分应尽可能描述性。例如,如果我们正在为 GET /groups/:id/projects 端点编写测试,我们不希望将其命名为 “GET projects endpoint”,因为还有一个 GET /projects 端点,它也获取用户在所有 GitLab 中有权访问的项目列表。
为了选择合适的名称,我们可以先查看我们的 API 文档,并以与文档中相同的方式命名它,同时确保名称使用句子大小写。因此,GET /groups/:id/projects 将被称为 GET list a group's projects,测试文件名为 get_list_a_groups_projects_helper.rb。GET /projects 将被称为 GET list all projects,测试文件名为 get_list_all_projects_helper.rb。
在某些情况下,被测试的提供者可能没有文档记录,因此在这些情况下,回退到以 HTTP 请求方法开头,后跟尽可能描述性的名称,以确保很容易判断该提供者的用途。
约定总结
| 测试类型 | 文件夹结构 | 命名约定 |
|---|---|---|
| 消费者测试 | 遵循 Rails 引用标准。例如,Project::Pipelines#index 将是 consumer/specs/project/pipelines/index.spec.js |
遵循 Rails 命名标准。例如,Project::Pipelines#index 将在 project 文件夹内称为 Pipelines#index。 |
| 提供者测试 | 类似于 Rails 控制器分组。例如,GET list project pipelines API 端点 将是 provider/pact_helpers/project/pipelines/get_list_project_pipelines_helper.rb |
遵循 API 文档命名方案,使用句子大小写。例如,GET /projects/:id/pipelines 将被称为 GET list project pipelines。 |