2023年3月24日

使用 Prisma 进行测试的终极指南:CI 流水线

持续集成 (CI) 指的是将不同作者的代码更改安全地集成到中央仓库的过程。在本文中,您将更详细地了解 CI 流水线是什么、如何配置 CI 流水线以及如何使用该流水线自动化您的测试。

The Ultimate Guide to Testing with Prisma: CI Pipelines

目录

引言

当您接近本系列的尾声时,请回顾一下您在前四篇文章中取得了哪些成就。您

  1. 模拟了 Prisma 客户端
  2. 学习并编写了单元测试
  3. 学习并编写了集成测试
  4. 学习并编写了端到端测试

您所学到的测试策略和概念将使您能够编写代码并验证新更改是否如您期望的那样在现有代码库中正常工作。

这种安心感非常重要,尤其是在大型团队中。然而,您所学到的东西有一个不足之处:在您进行更改时,需要手动运行测试。

在本文中,您将学习如何自动化测试运行,以便在对主分支提出拉取请求时,您的代码库更改将自动进行测试。

什么是持续集成流水线?

持续集成流水线描述了在发布软件新版本之前必须完成的一系列步骤。您可能见过或听过 CI/CD 这个缩写,它指的是持续集成持续部署。通常,这些独立的概念通过像您今天将要了解的流水线来处理。

就本文而言,您将主要关注 CI 部分,您将在其中构建、测试并最终合并您的代码。

有许多技术可以让您设置流水线,选择哪种技术通常取决于您正在使用的技术栈。例如,您可以在以下工具中设置流水线:

  • Jenkins
  • CircleCI
  • GitLab
  • AWS Codepipeline
  • 还有更多...

在本文中,您将学习如何使用 GitHub Actions 定义您的流水线,这将允许您配置流水线,以便在您向主分支创建拉取请求时,对代码更改运行测试。

您将使用的技术

先决条件

前置知识

在执行以下步骤时,具备以下知识会很有帮助

  • 使用 Git 的基本知识
  • 对 Docker 的基本了解

开发环境

为了跟进所提供的示例,您需要具备以下条件:

本系列大量使用了这个 GitHub 仓库。请务必克隆该仓库。

克隆仓库

在您的终端中,进入存储项目的目录。在该目录中运行以下命令:

上述命令会将项目克隆到名为 testing_mono_repo 的文件夹中。该仓库的默认分支是 main

您需要切换到 e2e-tests 分支,该分支包含上一篇文章中完整的端到端测试设置。

克隆仓库并检出正确的分支后,设置项目需要几个步骤。

首先,安装 node_modules

接下来,在项目根目录创建一个 .env 文件

将以下变量添加到该新文件中

.env 文件中,添加了以下变量:

  • API_SECRET:提供一个密钥,用于身份验证服务加密您的密码。在实际应用程序中,此值应替换为包含数字和字母的较长随机字符串。
  • DATABASE_URL:包含您数据库的 URL。
  • VITE_API_URL:Express API 的 URL 位置。

设置您自己的 GitHub 仓库

为了开始配置在 GitHub Actions 中运行的流水线,您首先需要拥有自己的 GitHub 仓库,并有一个 main 分支用于提交拉取请求。

前往 GitHub 网站并登录您的账户。

注意:如果您还没有 GitHub 账户,可以在此处免费创建一个。

登录后,点击下方所示的新建按钮以创建新仓库

New repository button in GitHub

在下一页,您将被要求提供一些关于您的仓库的信息。填写下方指示的字段,然后点击页面底部的创建仓库按钮

New repository form in GitHub

然后您将被导航到新仓库的主页。在顶部会有一个文本字段,允许您复制仓库的 URL。点击复制图标以复制 URL。

New repository url in GitHub

现在您已经获得了新 GitHub 仓库的 URL,在终端中进入代码库的根目录,并使用以下命令将项目来源指向新仓库(请务必在第二行插入您刚刚复制的 URL)

您将基于 e2e-tests 分支的进度进行工作,因此该分支应被视为 main。将 e2e-tests 合并到 main

最后,将项目推送到您的新仓库

设置工作流

您现在已经设置好了一个可以推送更改的仓库。下一个目标是当对您已创建的 main 分支进行或更新拉取请求时,触发一系列任务。

在使用 GitHub 时,您可以创建工作流文件来定义这些步骤。这些文件必须创建在项目根目录下的 .github/workflows 文件夹中。

在您的项目中创建一个名为 .github 的新文件夹

.github/workflows 文件夹中,创建一个名为 test.yml 的新文件,您将在其中定义测试工作流。

在该文件中,您将提供 GitHub Actions 准备项目并运行测试套件的步骤。

要启动此工作流,请使用 name 属性为您的工作流命名

该工作流现在将在 GitHub 中显示为 'Tests'

接下来要做的是配置此工作流,使其仅在对仓库的 main 分支发出拉取请求时运行。添加带有以下选项的 on 关键字来实现此目的

注意:请注意缩进。缩进在 YAML 文件中非常重要,不正确的缩进会导致文件失败。

现在您已经命名了工作流,并配置它仅在对 main 进行拉取请求或更新时运行。接下来,您将开始定义一个运行单元测试的任务。

注意:工作流文件中可以配置的选项非常多,它们会改变工作流的运行方式、功能等等……要查看完整列表,请查阅 GitHub 的文档

添加单元测试任务

为了定义与特定任务(称为步骤)相关的一组指令,您将使用 job 关键字。每个任务都在您配置的独立环境中运行其一系列步骤。

.github/workflows/tests.yml 文件中添加一个 jobs 部分,并指定一个名为 unit-tests 的任务

如前所述,每个独立的任务都在其自己的环境中运行。为了运行一个任务,您需要指定任务应该在哪种类型的机器上运行。

使用 runs-on 关键字指定任务应在 ubuntu-latest 机器上运行

您将定义的最后一个部分是 steps 部分,您将在此定义任务运行单元测试所需的一系列步骤。

将以下内容添加到 unit-tests 任务中

这定义了一个包含一个步骤的 steps 部分。该步骤使用预构建操作 v3 的 actions/checkout,它会检出您的 GitHub 仓库,以便您可以在任务内部与它交互。

注意:一个action是您可以在工作流中使用的单个步骤的集合。它们有助于将可重用的一系列步骤分解到一个文件中。

接下来,您需要定义一组步骤,用于在虚拟环境中安装 Node.js、安装 PNPM,并安装您的仓库包。

这些步骤将在您创建的每个测试任务中都需要,因此您将把它们定义在一个可重用的自定义操作中。

.github 目录下创建一个名为 actions 的新文件夹,并在 .github/actions 文件夹中创建一个名为 build 的文件夹。

然后在 .github/actions/build 中创建一个名为 action.yml 的文件。

在该文件中,粘贴以下内容

此文件定义了一个复合操作,它允许您在任务中使用此操作中定义的 steps

您上面添加的步骤执行以下操作:

  1. 在虚拟环境中设置 PNPM
  2. 在虚拟环境中设置 Node.js
  3. 在仓库中运行 pnpm install 以安装 node_modules

现在这个可重用操作已经定义,您可以在您的主工作流文件中使用它。

回到 .github/workflows/tests.yml,使用 uses 关键字来使用该自定义操作

此时,任务将检出仓库,设置虚拟环境并安装 node_modules。剩下要做的就是实际运行测试。

添加一个最后一步,运行 pnpm test:backend:unit 来运行单元测试。

注意:请注意,您使用 name 关键字将这个新步骤命名为 'Run tests',并使用 run 关键字运行了一个任意命令。

此任务现已完成并可进行测试。为了测试,首先将此代码推送到仓库的 main 分支

工作流现在已在 main 分支上定义。然而,只有当您对该分支提交拉取请求时,工作流才会被触发。

创建一个名为 new-branch 的新分支

在该新分支中,通过向 backend/src/index.ts 文件添加注释来进行微小更改

现在提交并将这些更改推送到远程仓库。仓库目前不知道有一个 new-branch 分支,因此您需要指定 origin 应该使用名为 new-branch 的分支来处理这些更改

新分支现在已在远程仓库中可用。创建一个拉取请求以将此分支合并到 main 分支中。

在浏览器中前往仓库。在页面顶部的拉取请求选项卡中,您应该看到一个比较并拉取请求按钮,因为 new-branch 最近有推送

GitHub PR tab

点击该按钮以打开拉取请求。您应该会被导航到一个新页面。在该新页面上,点击创建拉取请求按钮以打开拉取请求。

GitHub create PR page

打开拉取请求后,您应该会在合并拉取请求按钮上方看到一个黄色框,显示您的测试任务正在运行

PR page with unit tests running in a job.

如果您点击详情按钮,您应该会看到每个步骤的运行情况及其控制台输出。

一旦任务完成,您将收到工作流中的检查是否通过的通知

PR page with successful tests.

现在您的单元测试任务已完成,您将继续创建运行集成测试的任务。

注意:暂不要合并此拉取请求!您将在本文的其余部分重复使用此拉取请求。

添加集成测试任务

运行集成测试的过程与运行单元测试非常相似。此任务的区别在于,您的集成测试依赖于测试数据库和环境变量。在本节中,您将设置这些并定义一个任务来运行您的测试。

在开始进行更改之前,您需要再次检出仓库的 main 分支

首先将 unit-tests 任务复制到一个名为 integration-tests 的新任务中。同时,将该任务的最后一步中的 pnpm test:backend:unit 替换为 pnpm test:backend:int

有了这些,您已经具备了运行测试所需的大部分条件,但是按原样运行工作流将触发 scripts/run-integration.sh 文件的运行。该脚本使用 Docker Compose 启动测试数据库。

GitHub Actions 使用的虚拟环境默认不带 Docker Compose。为了使其正常工作,您将设置另一个自定义操作,将 Docker Compose 安装到环境中。

.github/actions 中创建一个名为 docker-compose 的新文件夹,并在其中创建一个名为 action.yml 的文件。

此操作应完成两项任务:

  1. 将 Docker Compose 插件下载到虚拟环境中
  2. 使插件可执行,以便可以使用 docker-compose 命令

将以下内容粘贴到 .github/actions/docker-compose/action.yml 中以处理这些任务

上面代码片段的第一步是将 Docker Compose 插件源下载到虚拟环境中的 /usr/local/bin/docker-compose。然后,它使用 chmod 将此源设置为可执行文件。

自定义操作完成后,将其添加到 .github/workflows/tests.yml 中的 integration-tests 任务中,就在运行测试的步骤之前

此测试所需的最后一件事是一组环境变量。您的应用程序期望的环境变量是:

  • DATABASE_URL:数据库的 URL
  • API_SECRET:用于签署 JWT 的身份验证密钥
  • VITE_API_URL:Express API 的 URL

您可以使用 env 关键字将它们添加到虚拟环境。环境变量可以添加到工作流级别(适用于所有任务),也可以添加到特定任务。在您的情况下,您将它们添加到工作流级别,以便每个任务都可以使用这些变量。

注意:通常最好的做法是仅将所需的环境变量单独暴露给每个任务。在本文中,为了简单起见,这些变量将被暴露给每个任务。

env 键添加到您的工作流并定义您需要的三个变量

此时,您可以提交并将这些更改推送到 main 分支以发布对工作流的更改

然后通过运行以下命令将这些更改合并到 new-branch 分支,以触发工作流的新运行

注意:在 git merge main 步骤,您将进入终端中的编辑器。输入 :qa 并按 enter 退出该编辑器。

此任务将比单元测试任务花费更长时间,因为它必须安装 Docker Compose、启动数据库,然后执行所有测试。

一旦任务完成,您应该会看到以下成功消息

Successfull integration and unit tests.

添加端到端测试任务

既然单元测试和集成测试都在工作流中运行,那么要定义的最后一组测试是端到端测试。

首先,再次检出 main 分支以更改工作流文件

与上一节的开头类似,将 integration-tests 任务的内容复制到一个名为 e2e-tests 的新任务中,将 pnpm backend:tests:int 替换为 pnpm test:e2e

在提交新任务之前,还需要做几件事:

  • 在虚拟环境中安装 Playwright 及其测试浏览器
  • 更新 scripts/run-e2e.sh

在此任务中安装 Docker Compose 的步骤之后,立即添加两个新步骤,用于下载 Playwright 并将其测试浏览器安装到项目的 e2e 文件夹中。

您还需要在 env 部分添加两个新的环境变量,Playwright 在安装时会用到它们

现在,当工作流运行时,Playwright 应该已正确安装和配置,以允许您的测试运行。

接下来要改变的是 scripts/run-e2e.sh 脚本运行端到端测试的方式。

目前,当端到端测试运行完成后,脚本会自动使用 npx playwright show-report 来提供结果报告。在 CI 环境中,您不希望发生这种情况,因为它会导致任务无限期运行,直到手动取消。

从脚本中删除该行

解决了这个问题后,您现在可以把更改推送到 main 并将这些更改合并到 new-branch 分支中

如果您回到浏览器中的拉取请求,您现在应该会看到有三个任务正在检查中运行。

新任务将需要很长时间才能完成,因为它必须下载 Docker Compose 和 Playwright 的浏览器,启动数据库并执行所有测试。

一旦任务完成,您应该会看到成功测试的完整列表

A complete set of successful jobs

总结与最终思考

在本文中,您了解了持续集成。更具体地说,您了解了:

  • 什么是持续集成
  • 它在您的项目中为何有用
  • 如何使用 GitHub Actions 设置 CI 流水线

最终,您拥有了一个 CI 流水线,它会自动对任何与 main 分支相关的拉取请求分支运行完整的测试套件。

这非常强大,因为它允许您在每个拉取请求上设置检查,以确保相关分支中的更改按预期工作。使用 GitHub 的安全设置,您还可以在这些检查不成功时阻止合并到 main 中。

在本系列课程中,您学习了可以针对应用程序运行的各种测试,如何针对使用 Prisma 与数据库交互的函数和应用程序编写这些测试,以及如何将这些测试应用于您的项目。

如果您对本系列中涵盖的任何内容有疑问,请随时通过 Twitter 与我联系。

不要错过下一篇文章!

订阅 Prisma 电子邮件通讯

© . All rights reserved.