写点什么

有赞前端质量保障体系

  • 2020-03-15
  • 本文字数:4885 字

    阅读完需:约 16 分钟

有赞前端质量保障体系

前言

最近一年多一直在做前端的一些测试,从小程序到店铺装修,基本都是纯前端的工作,刚开始从后端测试转为前端测试的时候,对前端东西茫然无感,而且团队内没有人做过纯前端的测试工作,只能一边踩坑一边总结经验,然后将容易出现问题的点形成体系、不断总结摸索,最终形成了目前的一套前端测试解决方案。在此,将有赞的前端质量保障体系进行总结,希望和大家一起交流。


先来全局看下有赞前端的技术架构和针对每个不同的层次,主要做了哪些保障质量的事情:




有赞的 Node 技术架构分为业务层、基础框架层、通用组件和基础服务层,我们日常比较关注的是基础框架、通用组件和业务层代码。Node 业务层做了两件事情,一是提供页面渲染的 client 层,用于和 C 端用户交互,包括样式、行为 js 等;二是提供数据服务的 server 层,用于组装后台提供的各种接口,完成面向 C 端的接口封装。


对于每个不同的层,我们都做了一些事情来保障质量,包括:


  • 针对整个业务层的 UI 自动化、核心接口|页面拨测;

  • 针对 client 层的 sentry 报警;

  • 针对 server 层的接口测试、业务报警;

  • 针对基础框架和通用组件的单元测试;

  • 针对通用组件变更的版本变更报警;

  • 针对线上发布的流程规范、用例维护等。


下面就来分别讲一下这几个维度的质量保障工作。

一、UI 自动化

很多人会认为,UI 自动化维护成本高、性价比低,但是为什么在有赞的前端质量保证体系中放在了最前面呢?


前端重用户交互,单纯的接口测试、单元测试不能真实反映用户的操作路径,并且从以往的经验中总结得出,因为各种不可控因素导致的发布 A 功能而 B 功能无法使用,特别是核心简单场景的不可用时有出现,所以每次发布一个应用前,都会将此应用提供的核心功能执行一遍,那随着业务的不断积累,需要回归的测试场景也越来越多,导致回归的工作量巨大。为了降低人力成本,我们亟需通过自动化手段释放劳动力,所以将核心流程回归的 UI 自动化提到了最核心地位。


当然,UI 自动化的最大痛点确实是维护成本,为降低维护成本,我们将页面分为组件维度、页面维度,并提供统一的包来处理公用组件、特殊页面的通用逻辑,封装通用方法等,例如初始化浏览器信息、环境选择、登录、多网点切换、点击、输入、获取元素内容等等,业务回归用例只需要关注自己的用例操作步骤即可。

1.1 框架选择

– puppeteer[1],它是由 Chrome 维护的 Node 库,基于 DevTools 协议来驱动 chrome 或者 chromium 浏览器运行,支持 headless 和 non-headless 两种方式。官网提供了非常丰富的文档,简单易学。


UI 自动化框架有很多种,包括 selenium、phantom;对比后发现 puppeteer 比较轻量,只需要增加一个 npm 包即可使用;它是基于事件驱动的方式,比 selenium 的等待轮询更稳当、性能更佳;另外,它是 chrome 原生支持,能提供所有 chrome 支持的 api,同时我们的业务场景只需要覆盖 chrome,所以它是最好的选择。


– mocha[2] + mochawesome[3],mocha 是比较主流的测试框架,支持 beforeEach、before、afterEach、after 等钩子函数,assert 断言,测试套件,用例编排等。


mochawesome 是 mocha 测试框架的第三方插件,支持生成漂亮的 html/css 报告。


js 测试框架同样有很多可以选择,mocha、ava、Jtest 等等,选择 mocha 是因为它更灵活,很多配置可以结合第三方库,比如 report 就是结合了 mochawesome 来生成好看的 html 报告;断言可以用 powser-assert 替代。

1.2 脚本编写

  • 封装基础库

  • 封装 pc 端、h5 端浏览器的初始化过程

  • 封装 pc 端、h5 端登录统一处理

  • 封装页面模型和组件模型

  • 封装上传组件、日期组件、select 组件等的统一操作方法

  • 封装 input、click、hover、tap、scrollTo、hover、isElementShow、isElementExist、getElementVariable 等方法

  • 提供根据 “html 标签>>页面文字” 形式获取页面元素及操作方法的统一支持

  • 封装 baseTest,增加用例开始、结束后的统一操作

  • 封装 assert,增加断言日志记录

  • 业务用例

  • 安装基础库

  • 编排业务用例

1.3 执行逻辑

  • 分环境执行

  • 增加预上线环境代码变更触发、线上环境自动执行

  • 监控源码变更

  • 增加 gitlab webhook,监控开发源码合并 master 时自动在预上线环境执行

  • 增加 gitlab webhook,监控测试用例变更时自动在生产环境执行

  • 每日定时执行

  • 增加 crontab,每日定时执行线上环境





二、接口测试

接口测试主要针对于 Node 的 server 层,根据我们的开发规范,Node 不做复杂的业务逻辑,但是需要将服务化应用提供 dubbo 接口进行一次转换,或将多个 dubbo 接口组合起来,提供一个可供 h5/小程序渲染数据的 http 接口,转化过程就带来了各种数据的获取、组合、转换,形成了新的端到端接口。这个时候单单靠服务化接口的自动化已经不能保障对上层接口的全覆盖,所以我们针对 Node 接口也进行自动化测试。为了使用测试内部统一的测试框架,我们通过 java 去请求 Node 提供的 http 接口,那么当用例都写好之后,该如何评判接口测试的质量?是否完全覆盖了全部业务逻辑呢?此时就需要一个行之有效的方法来获取到测试的覆盖情况,以检查有哪些场景是接口测试中未覆盖的,做到更好的查漏补缺。


– istanbul[4] 是业界比较易用的 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 文件的方式,来排除或者指定需要统计覆盖率的文件


verbose: falseinstrumentation:  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: falsereporting:  print: summary  reports:    - lcov  dir: ./coverage  watermarks:    statements: [50, 80]    lines: [50, 80]    functions: [50, 80]    branches: [50, 80]  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: falsecheck:  global:    statements: 0    lines: 0    branches: 0    functions: 0    excludes: []  each:    statements: 0    lines: 0    branches: 0    functions: 0    excludes: []
复制代码

三、单元测试

单元测试在测试分层中处于金字塔最底层的位置,单元测试做的比较到位的情况下,能过滤掉大部分的问题,并且提早发现 bug,也可以降低 bug 成本。推行一段时间的单测后发现,在有赞的 Node 框架中,业务层的 server 端只做接口组装,client 端面向浏览器,都不太适合做单元测试,所以我们只针对基础框架和通用组件进行单测,保障基础服务可以通过单测排除大部分的问题。比如基础框架中店铺通用信息服务,单测检查店铺信息获取;比如页面级商品组件,单测检查商品组件渲染的 html 是否和原来一致。


单测方案试行了两个框架:


  • Jest[5]

  • ava[6]


比较推荐的是 Jest 方案,它支持 Matchers 方式断言;支持 Snapshot Testing,可测试组件类代码渲染的 html 是否正确;支持多种 mock,包括 mock 方法实现、mock 定时器、mock 依赖的 module 等;支持 istanbule,可以方便的获取覆盖率。


总之,前端的单测方案也越来越成熟,需要前端开发人员更加关注 js 单测,将 bug 扼杀在摇篮中。

四、基础库变更报警

上面我们已经对基础服务和基础组件进行了单元测试,但是单测也不能完全保证基础库的变更完全没有问题,伴随着业务层引入新版本的基础库,bug 会进一步带入到业务层,最终影响 C 端用户的正常使用。那如何保障每次业务层引入新版本的基础库之后能做到全面的回归?如何让业务测试同学对基础库变更更加敏感呢?针对这种情况,我们着手做了一个基础库版本变更的小工具。实现思路如下:


1. 对比一次 master 代码的提交或 merge 请求,判断 package.json 中是否有特定基础库版本变更2. 将对应基础库的前后两个版本的代码对比发送到测试负责人3. 根据 changelog 判断此次回归的用例范围4. 增加 gitlab webhook,只有合并到合并发布分支或者 master 分支的代码才触发检查
复制代码


这个小工具的引入能及时通知测试人员针对什么需求改动了基础组件,以及这次基础组件的升级主要影响了哪些方面,这样能避免相对黑盒的测试。


第一版实现了最简功能,后续再深挖需求,可以做到前端代码变更的精准测试。


五、sentry 报警

在刚接触前端测试的时候,js 的报错没有任何追踪,对于排查问题和定位问题有很大困扰。因此我们着手引入了 sentry 报警监控,用于监控线上环境 js 的运行情况。


– sentry[7] 是一款开源的错误追踪工具,它可以帮助开发者实时监控和修复崩溃。


开始我们接入的方式比较简单粗暴,直接全局接入,带来的问题是报警信息非常庞大,全局上报后 info、warn 信息都会打出来。


更改后,使用 sentry 的姿势是:


  • sentry 的全局信息上报,并进行筛选

  • 错误类型: TypeError 或者 ReferenceError

  • 错误出现用户 > 1k

  • 错误出现在 js 文件中

  • 出现错误的店铺 > 2 家

  • 增加核心业务异常流程的主动上报


最终将筛选后的错误信息通过邮件的形式发送给告警接收人,在固定的时间集中修复。



六、业务报警

除了 sentry 监控报警,Node 接口层的业务报警同样是必不可少的一部分,它能及时发现 Node 提供的接口中存在的业务异常。这部分是开发和运维同学做的,包括在 Node 框架底层接入日志系统;在业务层正确的上报错误级别、错误内容、错误堆栈信息;在日志系统增加合理的告警策略,超过阈值之后短信、电话告警,以便于及时发现问题、排查问题。


业务告警是最能快速反应生产环境问题的一环,如果某次发布之后发生告警,我们第一时间选择回滚,以保证线上的稳定性。

七、约定规范

除了上述的一些测试和告警手段之外,我们也做了一些流程规范、用例维护等基础建设,包括:


  • 发布规范

  • 多个日常分支合并发布

  • 限制发布时间

  • 规范发布流程

  • 整理自测核心检查要点

  • 基线用例库

  • 不同业务 P0 核心用例定期更新

  • 项目用例定期更新到业务回归用例库

  • 线上问题场景及时更新到回归用例库


目前有赞的前端测试套路基本就是这样,当然有些平时的努力没有完全展开,例如接口测试中增加返回值结构体对比;增加线上接口或页面的拨测[8];给开发进行自测用例设计培训等等。也还有很多新功能探索中,如接入流量对比引擎,将线上流量导到预上线环境,在代码上线前进行对比测试;增加 UI 自动化的截图对比;探索小程序的 UI 自动化等等。


参考链接:



2020-03-15 20:201196

评论

发布
暂无评论
发现更多内容

浏览器拨测:将网站护航的阵地再前推一米

阿里巴巴云原生

阿里云 云原生 云拨测

全渠道商品计划软件:时尚鞋服企业的数字化新引擎与AI赋能

第七在线

在“黑天鹅”时代,如何锻造创业者的认知韧性?| 陶建辉演讲分享

TDengine

数据库 tdengine 时序数据库

汽车摆臂行业生产设备数据采集及集成

万界星空科技

mes #汽车 设备数据采集 汽车摆臂行业 汽车摆臂mes

AI智能体的开发流程

北京木奇移动技术有限公司

AI应用 AI智能体

牛客网最新的Java面试八股文通关手册

架构师之道

程序员 java面试

TikTok账号封号原因有哪些?

Ogcloud

TikTok tiktok运营 TikTok养号 tiktok封号

为什么任拓数据选择 NocoBase?自研转型最佳实践

NocoBase

开源 低代码 数字化转型 零代码 客户案例

人事人才信息管理系统:2024年10大推荐系统

易成研发中心

一行代码都不改,Golang 应用链路指标日志全知道!

阿里巴巴云原生

阿里云 云原生

苹果m1能玩steam吗,苹果笔记本玩steam游戏教程

阿拉灯神丁

游戏 MacBook steam M1芯片 CrossOver Mac下载

数据同步、流计算全面强化,TDengine 3.3.4.3 版本正式发布

TDengine

数据库 tdengine 时序数据库

工业公辅车间数智化节能头部企业,蘑菇物联选择 TDengine 升级 AI 云智控

TDengine

数据库 tdengine 时序数据库

盘点本轮牛市币价再创新高的「老山寨」

TechubNews

淘口令真实URL API接口的应用与收益

科普小能手

淘宝 API url API 接口 1688淘口令接口

YashanDB在地理信息系统(GIS)领域的关键功能和技术优势

YashanDB

yashandb 崖山数据库 地理信息系统

从仪表盘探索 MongoDB 关键指标

巴辉特

赣州银行新核心成功投产上线,分布式存储筑牢数字化转型根基

XSKY星辰天合

知乎启用AutoMQ替换Kafka,开辟成本优化与运维提效新纪元

AutoMQ

Java 数据库 kafka 客户案例

判断TikTok节点IP的纯净度高不高的几个方法

Ogcloud

tiktok运营 tiktok节点 tiktok网络 tiktok封号 tiktok代理节点

MES系统在传统制造业中的作用与战略价值

积木链小链

mes

最全Java面试题:数据结构+算法+JVM+线程+finalize+GC

采菊东篱下

java面试

探索1688阿里巴巴API接口:揭秘商品详情与关键字搜索的奥秘

代码忍者

API 接口 pinduoduo API

云桌面年终狂欢,多重福利等你来拿!

Finovy Cloud

云主机 云服务器 云桌面 云电脑

面试官:如何设计一个高并发系统?

了不起的程序猿

Java 程序员 面试 高并发 架构设计

翻倍只是山寨币季的点火阶段:市场分歧与未来趋势

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 公链开发 代币开发

不要小看一个Redis!从头到尾全是精华!

开心学Java

Java redis 程序员 面试 架构师

客户案例|大模型加持智能会议,金融机构实现“写纪要”到“审纪要”的飞跃

澜舟孟子开源社区

人工智能 大模型 智能办公

探索1688阿里巴巴API接口:图片搜索商品列表(拍立淘)与店铺所有商品列表的实战应用

代码忍者

API 接口 pinduoduo API

云数仓ByteHouse的湖仓一体设计与实践

字节跳动数据平台

大数据 数据仓库 湖仓一体

作为一名普通Java程序员,每次面试后是否有必要复盘?

了不起的程序猿

微服务 高并发 架构师 java面试 八股文

有赞前端质量保障体系_文化 & 方法_周清华_InfoQ精选文章