0%

单元测试与持续集成实践记录

top.png

背景

  • 特性验证的问题
    • 开发人员在进行开发、上线过程中,基本可以认为是 coding->testing->coding->testing 的循环。
    • 随着项目复杂度越来越高,testing 的成本自然越来越大。
    • 复杂度到达一定程度后,代码变更导致的 testing 成本会大到影响正常迭代,此时项目无法维护
    • 代码 review 与 merge 操作,会对开发人员带来越来越大的心智负担
    • 随着时间的推移,项目特性越来越多,越来越无法重构
  • 重复行为问题
    • 各项目测试环境发布次数不少,带来不少重复操作
  • 开发约束问题
    • 本地开发可以绕过约束 – 需要提供线上约束
too-busy-to-improve.png

分析

  • 针对 coding 和 testing:coding 是不明确的工作,每次都会有不一样的内容;而 testing 则是明确的工作,每次都是重复工作
  • 则针对 testing 的自动化,可以极大的释放生产力

单元测试落地

unit-test-cost.jpg
  • 给项目添加单元测试,并不单纯只是工具使用上的变化和代码量的增加,更为本质的变化,是代码设计上的变化、开发工作模式的变化
  • 上述变化,基本可以用一个词描述 – 学习成本

前端项目的单元测试落地针对的实际问题

  • 在实现 web 前端应用前,至少会考虑几个要点
    • 应用运行环境:pc 浏览器?移动端浏览器?app 内 webview?
    • 应用展示内容:banner?文案?按钮?图片?等等
    • 应用交互:点击按钮发生什么?输入文字发生什么?等等
  • 故对于 web 前端应用,其项目代码中,除了纯函数部分,还充斥着大量的 io 操作(service api 调用、bom api 调用、dom api)调用
  • 上述实现,就是一个个实际的测试用例

具体实践

  • 针对上述问题对应的测试用例,基本可以分为以下几种:

    • 纯函数测试:测试工具类纯函数是否符合预期
    • 展示性测试:用于测试组件内容是否正常展示,展示的各项内容是否完整、正确
    • 交互性测试:用于测试组件涉及的交互,是否可以正常输出,正常输出,并对输入、输出做校验
    • 快照测试:快照测试让开发人员明确自身对组件的修改,会有多大的波及度,具体可看Snapshot Testing
  • 其中交互测试是成本最高的测试,可以再细分为下面几种:

    • 涉及 dom 操作的交互测试
    • 涉及 bom 操作的交互测试
    • 涉及 service api 的操作交互测试
  • 另外,针对当前团队技术栈,还需要在 redux 场景下进行测试

  • 上述测试用例具体实践方式,可以看 react+react-router+react-redux 项目单元测试实践记录

  • 在具体实际中,针对一个组件的测试代码,其交互测试与其他测试测试代码对比,一般会是 6:1

成本与收益

  • 通过上面的论述,基本可以得出单元测试具体的成本描述

    • 基于当前技术栈单元测试学习成本
    • 测试代码开发成本
  • 另外也有单元测试具体的收益描述

    • 测试代码投入成本越高,则验证的成本越低
    • 项目迭代过程中,保证新特性不影响已有特性
    • 项目重构过程中,保证已有特性不受影响

持续集成落地

  • 持续集成投入很低,但收益很高
  • 持续集成,一般与 git 工作流结合使用,主要完成以下几个特性
    • 代码推送后,完成 code lint\unit test,给出报告
    • 代码请求合并前,完成 code lint\unit test,给出报告,有效减少 review 人的心智负担
    • 代码 review 完成后,进行自动化部署
top.png

具体实践

  • 当前团队使用 gitlab 服务进行版本管理,则可以使用 gitlab ci 对接 gitlab runner 完成持续集成

gitlab-runner 安装

  • 申请好机器后,在机器下载的 gitlab runner
1
sudo wget -O /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-386
  • 给 Gitlab-runner 添加执行权限:
1
sudo chmod +x /usr/local/bin/gitlab-runner
  • 创建一个 GitLab CI 用户
1
sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
  • 安装并启动服务
1
2
sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start

gitlab-runner 注册

  • runner 启动后,需要注册入 gitlab 服务中

  • 开始注册

1
sudo gitlab-runner register
  • 填入 Gitlab URL:
1
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com )
  • 然后输入注册 Runner 所需要的 token
    • token 会分为两种:Shared Runner(针对所有项目),Specific Runner (针对特定项目)
1
Please enter the gitlab-ci token for this runner
  • 输入 Runner 的 tags
1
2
Please enter the gitlab-ci tags for this runner (comma separated)
fe-ci
  • 选择 Runner 的执行者
1
2
Please enter the executor: ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell:
shell
  • 如果一切正常
1
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
  • 最后回到 gitlab,使用 admin 权限账号管理 runner,找到 ‘fe-ci’ runner,在 runner 中对对应项目启用,则 runner 配置完成

.gitlab-ci.yml 文件

  • 在项目根目录下创建 .gitlab-ci.yml 文件。以下是一份实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
stages:
- install
- codelint
- test

cache:
paths:
- node_modules/

install:node_modules:
stage: install
script:
- npm install
tags:
- fe-ci

codelint:
stage: codelint
script:
- npm run lint
tags:
- fe-ci

test:coverage:
stage: test
script:
- npm run test:coverage
tags:
- fe-ci
  • 可以看到 ci 脚本分为三个阶段
    • install: npm install – 安装依赖(node_modules)
    • codelint: npm run lint – 代码校验
    • test:coverage : npm run test:coverage – 全量单元测试并输出测试覆盖情况
  • cache: ... 部分表示 node_modules 需要缓存
  • tags: - fe-ci 表示此阶段指定使用 tags 为 ‘fe-ci’ 的 runner 进行执行

配置完成后实际运行

  • 代码推送后自动运行 code lint 和 unit testci_run_1.png
  • 在 merge request settings 中打开 pipeline 相关的约束mergeSetting.png
  • 则后续的 merge request 单,会需要 pipeline 运行成功后才能进行合并mr_result.png

参考

react+react-router+react-redux 项目单元测试实践记录
Gitlab 自动部署之二:安装 GITLAB-RUNNER

众筹开高达