NutUI React 之 PR 自动化测试

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 有几个核心的概念:

  1. Workflows(工作流):CI/CD 从开始到结束这个周期可以理解为一个工作流。工作流可以通过 yml 脚本配置,并且一个工作流可以包含一个 Job 或 多个 Job。
  2. Events(事件):触发 Workflows 的特定操作,例如:PR 创建,代码 Push 等。
  3. Jobs(任务):一个 Job 由一系列的步骤组成,其中每个步骤可以标注步骤名称,执行的脚本等。
  4. Actions(动作):每个步骤可以执行的处理,可以是一个或多个。
  5. 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,想要了解上面技术中更多的细节,可以加入我们的咚咚群进行交流。

加入我们

再次期待您早日成为我们共建大军中的一员! 一起共建,一起使用! 做站内最优秀的开源组件库!

相关推荐
zqx_71 小时前
随记 前端框架React的初步认识
前端·react.js·前端框架
惜.己1 小时前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5
什么鬼昵称2 小时前
Pikachu-csrf-CSRF(get)
前端·csrf
长天一色2 小时前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_2342 小时前
npm、yarn、pnpm之间的区别
前端·npm·node.js
秋殇与星河2 小时前
CSS总结
前端·css
BigYe程普3 小时前
我开发了一个出海全栈SaaS工具,还写了一套全栈开发教程
开发语言·前端·chrome·chatgpt·reactjs·个人开发
余生H3 小时前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
程序员-珍3 小时前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发
axihaihai3 小时前
网站开发的发展(后端路由/前后端分离/前端路由)
前端