转转QA Puppeteer 在客服业务线中的落地实践

笑哼 for 转转QA · October 02, 2019 · 785 hits

作者|赵里京

前言

UI自动化我们都了解可以模拟用户真正的使用场景和用户行为,而边界、异常等场景接口测试更加适合。那么实现了UI自动化是否就可以完全代替手工用例去执行测试任务。理论上没有错,但总是理想很丰满,现实很骨感。在做UI自动化时总会有那么多的问题阻碍了我们目标的实现:

  1. 脚本开发成本高而录制的脚本又基本无法重复使用;
  2. 脚本运行不稳定、问题的随机性;
  3. UI变化快脚本维护成本高等等等等。 那如何避免上述问题让我们可以做到更接近我们的目标?(下面的答案与上面的问题不一一对应)
  4. 测试和验证逻辑而非UI,我们减少页面上UI的验证、图片的识别等等。这些不稳定因素越少越稳定,并且你的UI用例思想都是以服务端的逻辑为主。如WebSocket发送方发送一条消息,接收方可以只验证接收到就好,至于样式用眼睛看可能会更轻松。
  5. 对于脚本不稳定以及问题的随机性,大部分原因是因为我们用例的健壮性不足导致。比如说,在你没有预测到的场景下用户发起的请求,和在你没有预测到的场景下系统的返回,这些没有预测到的情况就会导致用例失败,但这样的失败对于系统来说又是正常的。
  6. 互联网时代UI变化快,如果加上脚本开发的成本高,UI自动化将很难被测试使用。直到Puppeteer的出现,它提供了大量操作Chrome的API供开发者使用,使得开发速度快成本低。目前在我处的业务线中,小的需求半天就可以开发完成全部功能,供给开发进行测试使用。
  7. 最后一点就是写用例前你的用例工程框架设计的要合理些,这样便于后期的维护。下面就来简单介绍一下Puppeteer的一些相关内容。

Puppeteer介绍

Puppeteer是谷歌官方出品的一个通过DevTools协议控制headless Chrome的Node库,注意它只是一个node库,所以环境以及使用都很方便。我们可以通过Puppeteer提供的API直接控制浏览器,模拟大部分用户操作来进行UI Test或者作为爬虫访问页面来收集数据。
Puppeteer能做什么?

  1. 生成页面的截图和PDF。
  2. 抓取SPA并生成预先呈现的内容(即“SSR”服务端渲染)。
  3. 从网站抓取你需要的内容。
  4. 自动表单提交,UI测试,键盘输入等
  5. 创建一个最新的自动化测试环境。使用最新的JavaScript和浏览器功能,直接在最新版本的Chrome中运行测试。
  6. 捕获您的网站的时间线跟踪,以帮助诊断性能问题,Puppeteer Trace API。

Puppeteer环境安装

就不说了,网上海量资料供你选择

Puppeteer vs Selenium

  1. Puppeteer允许访问Chrome性能分析工具,来度量加载与渲染时间,可以进行页面性能测试。
  2. 由于谷歌的支持和对Chrome的复杂了解,Puppeteer可以更好地控制Chrome的浏览器,使测试用例运行的更加稳定。
  3. Puppeteer删除了对外部驱动程序的依赖以运行测试,使得环境更加轻量。而Selenium、Webdriver等,往往依赖众多,不够扁平,环境较重。
  4. Puppeteer默认设置为在无头模式下运行,也可以更改为在非无头模式下观看执行。

Puppeteer仍有些不足

  1. 到目前为止,Puppeteer仅限于Chrome浏览器,但Firefox的支持计划正在进行中。
  2. Puppeteer目前使用该工具的测试社区较小,而Selenium有更多针对测试的支持。

用例工程结构

多人协作一定要考虑维护的成本,工程的框架设计至关重要。结构清晰简单其他人维护的成本就会降低,下图为转转客服UI用例工程结构图:

主要是用Puppeteer+Mocha(摩卡)组合,Mocha与testNG的作用很像,主要也是用于单元测试的测试框架,也有测试套件等定义,以及用例控制功能。
上图第一层为用例的测试套件,一定要放置在工程的test文件夹下,下图中存在两个测试套件分别为IMmainProcess.test.js和WorkOrderIM.test.js。mocha.opts文件里写mocha执行命令的参数,如生成报告、执行方式等参数。
describe定义测试套件名称,it定义单个测试用例,Mocha同时提供了only,skip等控制用例执行方法和钩子函数before(),after()等。

(mocha生成的测试报告样式)

结构图中的逻辑层封装了逻辑变化校验,里面有大量的if else逻辑。如果触发一个动作后,会将页面实例传给逻辑变化模块进行校验,去判断当前页面是哪一种情况,进而来进行下一个动作,这就是前面说的用例健壮性的问题。当然在用例的什么位置加校验要通过个人的经验来判断。
业务逻辑中封装了浏览器实例减少重复代码,以及特定的业务逻辑。元素库主要封装的是global形式的页面元素常量。
最后就是经常用到的工具方法,比如httpclient,dbserver,以及发送邮件发送报警等工具。这些方法已经逐步封装成了API,其他同学只需下载npm包即可使用,使QA能将更多的精力放在用例逻辑的开发中。

使用Puppeteer过程中常遇到的问题

  1. 如何模拟多端以及不同的APP来打开同一M页 模拟不同的移动设备,首先Puppeteer提供了模拟移动设备的库,位置在工程的: /node_modules/puppeteer/DeviceDescriptors,我们可以直接引用,如模拟一个iPhone 6设备,下图为DeviceDescriptors文件配置: 使用方式: 模拟不同的APP,有些M页通过设置UA(userAgent)来告诉服务端所使用的是什么app,这样的逻辑我们可以修改DeviceDescriptors文件中对应配置的UA来实现。而直接修改Puppeteer库里的文件肯定不是好的,我们可将此文件拷到自己工程文件夹下进行修改并引用。下图为修改过的DeviceDescriptors文件,在userAgent中加入服务端识别的标识:
  2. 浏览器实例的封装降低重复代码 下图是封装的page模块,返回页面和浏览器实例。也可以将浏览器实例与用例写在同一文件中直接使用,免去了传参的麻烦,不过当用例过多时这样写就会产生大量的重复代码。
  3. 浏览器实例不会被关闭 在每条用例中都会有关闭浏览器实例的动作,但往往一段时间后服务器上就会驻留大量chrome实例,占用了服务器大量的资源,同时也有可能对后续的用例执行产生影响。即便使用try..catch{await browser.close()}这样的句子也无法解决问题。 官方解答是:“如果你想在 promise 执行完毕后无论其结果怎样都做一些处理或清理时,finally() 方法可能是有用的,它仅用于无论最终结果如何都要执行的情况”。此方法也确实有效。
  4. 元素位置不固定 M页中很多元素都是以feed流形式,所以位置有可能是这样的: body > div:nth-child(7) > div > div.ant-modal-wrap > div > div.ant-modal-content > div.ant-modal-body > div > p:nth-child(1) > div:nth-child(2) > div > div > div > ul > li:nth-child(5) 其中的数字在每次页面打开的时候都有可能发生变化,而同一类元素的路径结构一般不会变。对于这类问题解决原理,首先判断selector中存在几个数字。拿两个举例,那就定义一个二维数组的selector循环遍历,与给出的元素上面唯一标识进行比较,selector与唯一元素标识匹配成功则找到真实的页面元素的selector。方法封装的API: monitorapi.getSelector (page,selector,labelname)
  5. page,测试的页面实例,Object
  6. selector,任意一次的DOM元素位置,String
  7. labelname,元素展示的部分或全部内容,给出的内容保证页面中唯一
  8. returns selector,返回当前页面所选元素正确的selector定位

基于Puppeteer的UI用例监控系统

目前客服UI自动化用例同时肩负着监控线上客服系统功能回归的任务,并随之开发了用例配套系统“UI用例监控系统”,系统的核心仍然是“用例”。当执行线上用例失败后,系统首先会截取当前浏览器的快照,并将快照与异常结果一同上报至平台,同时发送报警信息给相关负责人。下图为系统中异常的记录,主要有异常信息、发生时间、执行人(获取的是系统用户名)、操作以及截屏图片等。

操作的备注功能功能主要是对异常数据人工打标,上报的数据将和标注后的数据进行对比。标注有两个属性分别为是否为bug与类别,如下图:

新产生的异常首先与库中异常数据进行比较,匹配后再以图片进行比较。如果均匹配成功则自动补充样本的标注信息,如果未匹配则不补充。同时如果与不是bug的匹配成功的话则不发报警信息,来减少误报情况。

系统核心模块如下图:

系统还有一些其他功能:

  1. 监控用例的两种执行方式 监听:集群上线完成后,会发送上线完成消息,监控平台收到消息后,会自动触发在服务器上的用例。当然消息会以集群名进行区分,用例有选择性的去执行。 定时任务:在centos服务器上创建定时任务,来定时触发用例监控线上功能。
  2. 执行人监控 目前用例分为线上和线下模式,由开关控制。用例场景完全一样,用户区分为线上和线下用户。但无论执行哪种模式,在哪执行用例,一旦发生异常都会上报至监控平台。这样你就可以清楚的知道,你的用例被人执行的情况与频率。
    1. 接入平台方式 一个API即可,并且自动帮助截取异常时的屏幕快照,不限制框架的使用,不限制用例编写的规范,只要是使用node环境的就可以。接入平台的API如下:monitorapi.FailMessage(e,casename,isOffline,...page)
    2. e,异常信息,或自己定义的error,String
    3. casename,用例名称,String
    4. isOffline,线上线下标识,int或String
    5. page,测试的页面实例,{...any} Object
    6. returns void
    7. (自带异常时截取屏幕快照功能,并发送给监控平台)

在业务线中的具体应用

客服系统核心功能之一是用户与机器人交互与人工客服聊天,最初的测试方式是采用java创建多个WebSocketClient与服务端建立连接,写心跳逻辑与服务端保持连接,进而模拟消息发送与接收。全场景用例写好后,相当于写好了一个没有页面的用户端,成本非常高。
而使用Puppeteer实现WebSocket场景就相当简单了,可以快速创建多个Chrome实例模拟多个用户登陆并与机器人进行交互、申请人工,客服优先级接待等复杂场景。这些多用户场景用手动测试很难,但使用UI自动化还是非常理想的。目前这些复杂场景用例,已经提供开发自测或者执行冒烟用例时使用。

未来规划

  1. 仍然是用例,用例覆盖的场景,用例的健壮性,仍然是基础与重点。
  2. 平台会增加用例管理,与报告展示等基础功能。
  3. UI层面的自动生成用例也是一个重点研究方向。
No Reply at the moment.
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up