埋點一直是 B 站 HTML5 播放器開發和測試過程中的一個痛點,埋點的種類和介面參數很多,測試很麻煩也很容易出錯。
雖然測試很麻煩,但它們的規則都很簡單,比如點擊或 hover 一個按鈕、錯誤上報、播放和性能上報,那麼能不能通過自動化的 E2E 測試來代替這些又繁瑣又機械化又容易出錯的測試工作呢?
在一次埋點線上事故後,我花了一天時間做了一些探索,最後效果還不錯,在這裡做一下簡單的總結。
編寫測試腳本#
模擬用戶操作就需要用到無頭瀏覽器,我採用了 Jest + Puppeteer 的組合。
Jest 是一個測試框架,Puppeteer 是用來控制 Chrome 或 Chromium。
選擇 Jest 是因為我對 Jest 最熟悉,然後又找到了一個 preset: jest-puppeteer,不是必需的,但它可以簡化很多 Puppeteer 操作。
安裝依賴:
npm install --save-dev jest jest-puppeteer puppeteer
測試腳本很簡單:
describe('log', () => {
beforeAll(async () => {
page.goto('https://www.bilibili.com/video/av44890855');
});
it('play_screen', async (done) => {
page.on('request', (request) => {
if (request.url().match(/^https:\/\/data\.bilibili\.com\/log\/web\?play_screen...參數參數/)) {
done();
}
});
page.click('video');
});
});
讓 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。
launch: {
executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
}
測試通過。
Chrome as a service#
剛才使用了本地的 Chrome,會依賴本地環境,而且想作為自動化測試跑在測試機上也是不行的。
所以我又在測試機上跑了一個 docker 容器:browserless/chrome,它可以把 Chrome 當做一個 service,測試腳本使用 websocket 協議操作 docker 里的 Chrome,這樣就避免了依賴本地 Chrome。
啟動容器:
docker pull browserless/chrome:release-chrome-stable
docker run -d -p 3000:3000 browserless/chrome:release-chrome-stable
使用:
connect: {
browserWSEndpoint: 'ws://localhost:3000'
}
劫持 js#
這樣用的是線上版本,根本沒有測試本地代碼啊!
哦,忘了說了,還需要把線上 js 劫持為本地版本。
await page.setRequestInterception(true);
page.goto('https://www.bilibili.com/video/av44890855');
page.on('request', (request) => {
if (request.url().match(/player\.js/)) {
request.respond({
status: 200,
contentType: 'application/javascript',
body: fs.readFileSync('dist/release/player.js').toString()
});
} else {
request.continue();
}
});