HeadlessChrome自动化测试探索

Auth:焱讲       Date:2019/12/8       Cat:软件测试       Word:共1847字

已关闭评论
文章目录 「隐藏」
  1. 编写测试脚本
  2. Chrome as a service
  3. 劫持 js

埋点一直是B站 HTML5 播放器开发和测试过程中的一个痛点,埋点的种类和接口参数很多,测试很麻烦也很容易出错

虽然测试很麻烦,但它们的规则都很简单,比如点击或 hover 一个按钮、错误上报、播放和性能上报,那么能不能通过自动化的 E2E 测试来代替这些又繁琐又机械化又容易出错的测试工作呢?

在一次埋点线上事故后,我花了一天时间做了一些探索,最后效果还不错,在这里做一下简单的总结

编写测试脚本

模拟用户操作就需要用到无头浏览器,我采用了 Jest + Puppeteer 的组合

Jest 是一个测试框架,Puppeteer 是用来控制 Chrome 或 Chromium

选择 Jest 是因为我对 Jest 最熟悉,然后又找到了一个 preset: jest-puppeteer,不是必需的,但它可以简化很多 Puppeteer 操作

安装依赖:

1 npm install --save-dev jest jest-puppeteer puppeteer

测试脚本很简单:

1 describe('log', () => {
2 beforeAll(async () => {
3 page.goto('https://www.bilibili.com/video/av44890855');
4 });
5
6 it('play_screen', async (done) => {
7 page.on('request', (request) => {
8 if (request.url().match(/^https:\/\/data\.bilibili\.com\/log\/web\?play_screen...参数参数/)) {
9 done();
10 }
11 });
12 page.click('video');
13 });
14 });

让 HeadlessChrome 打开一个播放页,监控页面请求的接口,模拟点击 video 元素,监控到浏览器请求了 play_screen 埋点即测试成功

看起来没什么问题,开开心心地执行了测试,结果 failed

发生了什么?配置 headless: false 观看了一下测试过程

发现是因为检测到浏览器不支持 HTML5 播放器,加载了 Flash 播放器

Puppeteer 文档里说道

Puppeteer is bundled with Chromium–not Chrome…Puppeteer does not support licensed formats such as AAC or H.264

解决方法也很简单,把 Puppeteer 自带的 Chromium 换成本地的 Chrome

1 launch: {
2 executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
3 }

测试通过

Chrome as a service

刚才使用了本地的 Chrome,会依赖本地环境,而且想作为自动化测试跑在测试机上也是不行的

所以我又在测试机上跑了一个 docker 容器:browserless/chrome,它可以把 Chrome 当做一个 service,测试脚本使用 websocket 协议操作 docker 里的 Chrome,这样就避免了依赖本地 Chrome

启动容器:

1 docker pull browserless/chrome:release-chrome-stable
2 docker run -d -p 3000:3000 browserless/chrome:release-chrome-stable

使用:

1 connect: {
2 browserWSEndpoint: 'ws://localhost:3000'
3 }

劫持 js

这样用的是线上版本,根本没有测试本地代码啊!

哦,忘了说了,还需要把线上 js 劫持为本地版本

1 await page.setRequestInterception(true);
2
3 page.goto('https://www.bilibili.com/video/av44890855');
4 page.on('request', (request) => {
5 if (request.url().match(/player\.js/)) {
6 request.respond({
7 status: 200,
8 contentType: 'application/javascript',
9 body: fs.readFileSync('dist/release/player.js').toString()
10 });
11 } else {
12 request.continue();
13 }
14 });

评论已关闭!