NutUI 是一款京东风格的移动端组件库。NutUI 目前支持 Vue 和 React技术栈,支持Taro多端适配。
期待您早日成为我们共建大军中的一员!
官网地址: 点击进入
GitHub地址: 点击进入
欢迎共建、使用!
背景
NUtUI React 在进行从 1.x 到 2.x 的改造升级工作。在这个过程中,每个 PR 都需要进行 Review,除了对代码的规范进行 Review 外,还需要对每个组件的单元测试进行 Review。通常情况下,我们通过在 CI/CD 中跑整体的单元测试来验证组件库的单元测试情况。但在单独组件进行改造的时候,有可能会关联修改其他组件,而没有修改其他组件的单元测试。所以基于这样的情况,我们想优先跑 PR 所修改组件的单元测试。
NutUI React 的 PR 自动化测试主要依赖与 GitHub Actions。所以接下来,我们先看一下 GitHub Actions 的基础使用,然后在深入到 NutUI React 的 PR 自动化测试的实现。
GitHub Actions 介绍
GitHub Actions 是 GitHub 提供的一项功能,可以用来在 GitHub 上创建、测试、部署应用程序。它是一个自动化工作流程平台,可以通过触发事件来执行一系列操作,例如自动化测试,打包构建等。
GitHub Actions 有几个核心的概念:
- Workflows(工作流):CI/CD 从开始到结束这个周期可以理解为一个工作流。工作流可以通过 yml 脚本配置,并且一个工作流可以包含一个 Job 或 多个 Job。
- Events(事件):触发 Workflows 的特定操作,例如:PR 创建,代码 Push 等。
- Jobs(任务):一个 Job 由一系列的步骤组成,其中每个步骤可以标注步骤名称,执行的脚本等。
- Actions(动作):每个步骤可以执行的处理,可以是一个或多个。
- Runners(执行器):workflows 运行的容器。
上手 GitHub Actions
在仓库中创建 .github/workflows
文件。
在 .github/workflows
目录中,创建 test.yml
,这里只是举例,文件可以定义其他名字。
yaml
name: test
on:
push:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: echo something
- run: echo 'Hello World'
这段代码创建了一个名为 test 的工作流,当对 main 分支进行 push 的时候会触发此工作流的执行。工作流中有一个名为 test 的 Job,运行在 ubuntn 容器中,输出 Hello World
。(更多语法可参考这里)
自动化测试实践
单元测试可以分为两种方式处理:通过 Jest 处理全部的单元测试;通过识别变更文件,执行相关组件的单元测试。NutUI React 现在采用的是识别变更文件的方式来处理单元测试。
识别变更文件的方案需要借助 GitHub API 解析出变更文件,之后对变更文件的特征进行处理,识别出组件,执行单元测试。
GitHub 提供了 /repos/{owner}/{repo}/pulls/{pull_number}/files
API 用于查询 Pull Request 的相关内容。
要使用此 API ,我们需要提供 owner、repo、pull number 这三个参数的内容。owner、repo 和 pull number 可以通过 GitHub Action 中的上下文来获取:
yml
name: CI
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Get PR info
run: |
echo "PR Message github.event.number: ${{ github.event.number }}"
echo "PR Message github.repository: ${{ github.repository }}"
这里给出了一段 GitHub Action 的脚本,在 Get PR info
任务中,借助 linux 的 echo 命令,打印来 github.event.number 和 github.repository。想要对这段脚本进行测试,可将其提交到 .github/workflows/test.yml
中,然后通过其他分支向目标分支创建 PR。(备注:github.event.number
来自Webhook 的共有属性)
通过执行上述代码,我们可以看到输出的 PR 的 ID 和 repository。接下来要使用他们调用 GitHub 提供的 API。这段代码使用 curl 调用的 GitHub API:
yml
pr_number=${{ github.event.number }}
files_url="https://api.github.com/repos/${{ github.repository }}/pulls/$pr_number/files"
files_response=$(curl -sSL -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" $files_url)
这段代码中即有 ${{ xx }}
又有 $xx
,我们需要先区分什么时候使用什么形式。${{}}
是 GitHub 提供的插值表达式,在 GitHub Actions 执行的时候会对这种表达式进行求值。$xx
是 Linux shell 的变量调用的方式,在这段 GitHub Actions 中我们实际执行的主要是 Linux shell。
shell 声明变量的方式如下:
shell
shellVariable=1
调用变量的方式如下:
shell
echo "$shellVariable"
通过 curl 获取到 GitHub API 返回的结果后,需要对结果进行处理,即提取变更文件。
yml
files_changed=$(echo "$files_response" | jq -r '.[].filename')
echo "PR files: $files_changed"
component=$(echo "$files_changed" | grep -E -i 'src\/packages\/([a-z]+)(\/[a-z_\.]*)*' | sed -E 's/src\/packages\/([a-z]+)(\/[a-z_\.]*)*/\1/i' | awk 'END{print}')
npm test -- $component
因为 GitHub API 返回的是 JSON 格式:
shell
[
{
"sha": "bbcd538c8e72b8c175046e27cc8f907076331401",
"filename": "src/packages/button/button.tsx",
"status": "added",
"additions": 103,
"deletions": 21,
"changes": 124,
"blob_url": "https://github.com/octocat/Hello-World/blob/6dcb09b5b57875f334f61aebed695e2e4193db5e/file1.txt",
"raw_url": "https://github.com/octocat/Hello-World/raw/6dcb09b5b57875f334f61aebed695e2e4193db5e/file1.txt",
"contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/file1.txt?ref=6dcb09b5b57875f334f61aebed695e2e4193db5e",
"patch": "@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"
}
]
所以我们通过 jq 从 GitHub API 返回的结果中提取我们需要的数据,即第一行代码中的 jq -r '.[].filename
,这句代码的意思是取 filename
字段的值,然后以原始文本形式返回。对于上面的 JSON 数据,jq 的处理结果是:src/packages/button/button.tsx
。(jq 介绍)
获取变更文件后,还需要将src/packages/button/button.tsx
中的 button 提取出来,以便传递给 npm 脚本。对于变更文件的处理,主要借助 Linux 中的 grep、sed、awk。
grep -E -i
表示使用正则表达式,并且忽略大小写。 sed -E
同样表示使用正则表达式,但是它的忽略大小写是写到后面的参数中。
到这就完成了 NutUI React PR 自动化测试的 workflow,想要了解上面技术中更多的细节,可以加入我们的咚咚群进行交流。
加入我们
再次期待您早日成为我们共建大军中的一员! 一起共建,一起使用! 做站内最优秀的开源组件库!