商城的前端质量保障系统建设如何才能做到位?(上)
前言最近一年多一直在做前端的一些测试,从小程序到店铺装修,基本都是纯前端的工作,刚开始从后端测试转为前端测试的时候,对前端东西茫然无感,而且团队内没有人做过纯前端的测试工作,只能一边踩坑一边总结经验,然后将容易出现问题的点形成体系、不断总结摸索,最终形成了目前的一套前端测试解决方案。在此,将有赞的前端质量保障体系进行总结,希望和大家一起交流。
先来全局看下有赞前端的技术架构和针对每个不同的层次,主要做了哪些保障质量的事情:
有赞的 Node 技术架构分为业务层、基础框架层、通用组件和基础服务层,我们日常比较关注的是基础框架、通用组件和业务层代码。Node 业务层做了两件事情,一是提供页面渲染的 client 层,用于和 C 端用户交互,包括样式、行为 js 等;二是提供数据服务的 server 层,用于组装后台提供的各种接口,完成面向 C 端的接口封装。
对于每个不同的层,我们都做了一些事情来保障质量,包括:
针对整个业务层的 UI 自动化、核心接口|页面拨测;
针对 client 层的 sentry 报警;
针对 server 层的接口测试、业务报警;
针对基础框架和通用组件的单元测试;
针对通用组件变更的版本变更报警;
针对线上发布的流程规范、用例维护等。
下面就来分别讲一下这几个维度的质量保障工作。
一、UI自动化
很多人会认为,UI 自动化维护成本高、性价比低,但是为什么在有赞的前端质量保证体系中放在了最前面呢?
前端重用户交互,单纯的接口测试、单元测试不能真实反映用户的操作路径,并且从以往的经验中总结得出,因为各种不可控因素导致的发布 A 功能而 B 功能无法使用,特别是核心简单场景的不可用时有出现,所以每次发布一个应用前,都会将此应用提供的核心功能执行一遍,那随着业务的不断积累,需要回归的测试场景也越来越多,导致回归的工作量巨大。为了降低人力成本,我们亟需通过自动化手段释放劳动力,所以将核心流程回归的 UI 自动化提到了最核心地位。
当然,UI 自动化的最大痛点确实是维护成本,为降低维护成本,我们将页面分为组件维度、页面维度,并提供统一的包来处理公用组件、特殊页面的通用逻辑,封装通用方法等,例如初始化浏览器信息、环境选择、登录、多网点切换、点击、输入、获取元素内容等等,业务回归用例只需要关注自己的用例操作步骤即可。
1.框架选择
-- puppeteer,它是由 Chrome 维护的 Node 库,基于 DevTools 协议来驱动 chrome 或者 chromium 浏览器运行,支持 headless 和 non-headless 两种方式。官网提供了非常丰富的文档,简单易学。
UI 自动化框架有很多种,包括 selenium、phantom;对比后发现 puppeteer 比较轻量,只需要增加一个 npm 包即可使用;它是基于事件驱动的方式,比 selenium 的等待轮询更稳当、性能更佳;另外,它是 chrome 原生支持,能提供所有 chrome 支持的 api,同时我们的业务场景只需要覆盖 chrome,所以它是最好的选择。
-- mocha + mochawesome,mocha 是比较主流的测试框架,支持 beforeEach、before、afterEach、after 等钩子函数,assert 断言,测试套件,用例编排等。
mochawesome 是 mocha 测试框架的第三方插件,支持生成漂亮的 html/css 报告。
js 测试框架同样有很多可以选择,mocha、ava、Jtest 等等,选择 mocha 是因为它更灵活,很多配置可以结合第三方库,比如 report 就是结合了 mochawesome 来生成好看的 html 报告;断言可以用 powser-assert 替代。
2.脚本编写
封装基础库
封装 pc 端、h5 端浏览器的初始化过程
封装 pc 端、h5 端登录统一处理
封装页面模型和组件模型
封装上传组件、日期组件、select 组件等的统一操作方法
封装 input、click、hover、tap、scrollTo、hover、isElementShow、isElementExist、getElementVariable 等方法
提供根据 “html 标签>>页面文字” 形式获取页面元素及操作方法的统一支持
封装 baseTest,增加用例开始、结束后的统一操作
封装 assert,增加断言日志记录
业务用例
安装基础库
编排业务用例
3.执行逻辑
分环境执行
增加预上线环境代码变更触发、线上环境自动执行
监控源码变更
增加 gitlab webhook,监控开发源码合并 master 时自动在预上线环境执行
增加 gitlab webhook,监控测试用例变更时自动在生产环境执行
每日定时执行
增加 crontab,每日定时执行线上环境
二、接口测试
接口测试主要针对于 Node 的 server 层,根据我们的开发规范,Node 不做复杂的业务逻辑,但是需要将服务化应用提供 dubbo 接口进行一次转换,或将多个 dubbo 接口组合起来,提供一个可供 h5/小程序渲染数据的 http 接口,转化过程就带来了各种数据的获取、组合、转换,形成了新的端到端接口。这个时候单单靠服务化接口的自动化已经不能保障对上层接口的全覆盖,所以我们针对 Node 接口也进行自动化测试。为了使用测试内部统一的测试框架,我们通过 java 去请求 Node 提供的 http 接口,那么当用例都写好之后,该如何评判接口测试的质量?是否完全覆盖了全部业务逻辑呢?此时就需要一个行之有效的方法来获取到测试的覆盖情况,以检查有哪些场景是接口测试中未覆盖的,做到更好的查漏补缺。
istanbul 是业界比较易用的 js 覆盖率工具,它利用模块加载的钩子计算语句、行、方法和分支覆盖率,以便在执行测试用例时透明的增加覆盖率。它支持所有类型的 js 覆盖率,包括单元测试、服务端功能测试以及浏览器测试。
但是,我们的接口用例写在 Java 代码中,通过 Http 请求的方式到达 Node 服务器,非 js 单测,也非浏览器功能测试,如何才能获取到 Node 接口的覆盖率呢?
解决办法是增加 cover 参数:--handle-sigint,通过增加 --handle-sigint 参数启动服务,当服务接收到一个 SIGINT 信号(linux 中 SIGINT 关联了 Ctrl+C),会通知 istanbul 生成覆盖率。这个命令非常适合我们,并且因此形成了我们接口覆盖率的一个模型:
1. istanbule --handle-sigint 启动服务
2. 执行测试用例
3. 发送 SIGINT结束istanbule,得到覆盖率
最终,解决了我们的 Node 接口覆盖率问题,并通过 jenkins 持续集成来自动构建:
当然,在获取覆盖率的时候有需求文件是不需要统计的,可以通过在根路径下增加 .istanbule.yml 文件的方式,来排除或者指定需要统计覆盖率的文件:
<font size="3">verbose: false
instrumentation:
root: .
extensions:
- .js
default-excludes: true
excludes:['**/common/**','**/app/constants/**','**/lib/**']
embed-source: false
variable: __coverage__
compact: true
preserve-comments: false
complete-copy: false
save-baseline: false
baseline-file: ./coverage/coverage-baseline.json
include-all-sources: false
include-pid: false
es-modules: false
reporting:
print: summary
reports:
- lcov
dir: ./coverage
watermarks:
statements:
lines:
functions:
branches:
report-config:
clover: {file: clover.xml}
cobertura: {file: cobertura-coverage.xml}
json: {file: coverage-final.json}
json-summary: {file: coverage-summary.json}
lcovonly: {file: lcov.info}
teamcity: {file: null, blockName: Code Coverage Summary}
text: {file: null, maxCols: 0}
text-lcov: {file: lcov.info}
text-summary: {file: null}
hooks:
hook-run-in-context: false
post-require-hook: null
handle-sigint: false
check:
global:
statements: 0
lines: 0
branches: 0
functions: 0
excludes: []
each:
statements: 0
lines: 0
branches: 0
functions: 0
excludes: []</font>
页:
[1]