Puppeteer 初探之前端自動化測試

騰訊雲加社群發表於2019-03-03
歡迎大家前往騰訊雲技術社群,獲取更多騰訊海量技術實踐乾貨哦~


作者:林淙源 

導語: Most things that you can do manually in the browser can be done using Puppeteer!

初識puppeteer

puppeteer 翻譯是操縱木偶的人,利用這個工具,我們能做一個操縱頁面的人。puppeteer是一個nodejs的庫,支援呼叫Chrome的API來操縱Web,相比較Selenium或是PhantomJs,它最大的特點就是它的操作Dom可以完全在記憶體中進行模擬既在V8引擎中處理而不開啟瀏覽器,而且關鍵是這個是Chrome團隊在維護,會擁有更好的相容性和前景。

puppeteer功能

1.利用網頁生成PDF、圖片
2.爬取SPA應用,並生成預渲染內容(即“SSR” 服務端渲染)
3.可以從網站抓取內容
4.自動化表單提交、UI測試、鍵盤輸入等
5.幫你建立一個最新的自動化測試環境(chrome),可以直接在此執行測試用例
6.捕獲站點的時間線,以便追蹤你的網站,幫助分析網站效能問題

安裝 puppeteer

yarn add puppeteer
# or "npm i puppeteer"
複製程式碼

可能會遇到 無法下載Chromium 問題

是因為在執行安裝的過程中需要執行install.js,這裡會下載Chromium,官網建議是進行跳過,我們可以執行 —ignore-scripts 忽略這個js執行

./node/npm i --save puppeteer --ignore-scripts
複製程式碼

接下來我們需要去下載Chromium,windows的版本我這裡已經下載好了,直接解壓縮附件中的到 node_modules/puppeteer中就可以了。

執行下,我們建立一個檔案index.js,檔案內容

const puppeteer = require(`puppeteer`);

(async () => {
      const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto(`https://y.qq.com`);
    await page.screenshot({path: `yqq.png`});
    browser.close();
})();
複製程式碼

這段程式碼會開啟 y.qq.com 並截圖,我們執行

node  index.js
複製程式碼

如果看到目錄下有生成圖片y.qq.png的話,恭喜你,我們可以開始繼續往下學習puppeteer了。

體驗第一個demo,數字專輯自動購買的UI自動化測試

這裡測試的功能是自動拉登入購買一張數字專輯,並在購買成功後跳轉到銘牌頁,先看下整個流程吧。

首先我們先建立一個裝置,文件中(github.com/GoogleChrom…)
我們能看到,預設支援的裝置數量還是很多的,除了這些預設的裝置之外,我們還可以自定義自己的裝置,後面在呼叫emulate方法時會提到:

我們這裡暫時先建立系統提供的iphone6裝置,完了我們定義一個延時的timeout函式

const puppeteer = require(`puppeteer`);
const devices = require(`puppeteer/DeviceDescriptors`);
const iPhone = devices[`iPhone 6`];
let timeout = function (delay) {
     return new Promise((resolve, reject) => {   
           setTimeout(() => {   
                  try {
                      resolve(1)
                  } catch (e) {
                      reject(0)
                   }
           }, delay);
     })
 }
複製程式碼

接下來我們建立一個瀏覽器例項,並開啟一個頁面,細心的你一定發現在建立瀏覽器的時候我們傳了headless引數,如果設為true的話就能可以在不開啟外部瀏覽器的情況下完全利用v8引擎來進行頁面的測試,簡單說就是頁面以及Dom完全在記憶體中,就連瀏覽器事件也是在記憶體中去模擬觸發。

 const browser = await puppeteer.launch({
      headless:false //這裡我設定成false主要是為了讓大家看到效果,設定為true就不會開啟瀏覽器
 });

 const page = await browser.newPage();
複製程式碼

建立好瀏覽器例項之後我們需要讓頁面模擬成iphone6,這裡的emulate函式的引數你也可以自定義引數

await page.emulate(iPhone);
引數:
 {
    `name`: `Galaxy S5`, //裝置名
    `userAgent`: `Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Mobile Safari/537.36`, //UA
    `viewport`: {
      `width`: 360,//螢幕寬度
      `height`: 640,//螢幕高度
      `deviceScaleFactor`: 3,//縮放比例
      `isMobile`: true,//是否是移動裝置
      `hasTouch`: true,//是否支援touch事件
      `isLandscape`: false//是否橫屏
    }
  }
複製程式碼

好接下來我們就可以寫我們的測試步驟了。

第一步:我們開啟頁面,考慮到有資料需要非同步載入,我們在延遲1000ms後呼叫screenshot方法截圖留作日誌。

console.log("進入頁面");
await page.goto(`https://y.qq.com/m/digitalbum/gold/index.html?_video=true&id=2210323&g_f=tuijiannewupload#index/fans`);
await timeout(1000);
await page.screenshot({
     path: `1.png`
 });
複製程式碼

第二步:模擬觸發點選 立即購買按鈕,這時候會因為沒有登入態而開啟QQ登入。

console.log("點選立即購買按鈕");
await page.tap(`.js_sale_buyalbum`);
await page.screenshot({
    path: `2.png`
 });
複製程式碼

第三步:在輸入框中輸入帳號密碼,模擬輸入需要我們先呼叫tap方法模擬點選輸入框,tap引數就是元素selector,再用type方法進行輸入,輸入完了之後在模擬點選登入按鈕,登入完了之後我們延遲一段時間截圖,順利的話我們就能重新回到之前的售賣頁首頁,而底下usrbar因為有了登入態也展示了出來。

console.log("登入");
await page.tap("#u"); //直接操作dom選擇器,是不是很方便
await page.type("521017853");

await page.tap("#p");
await page.type("*********");//這裡密碼就不展示了哈

await page.tap("#go");

await timeout(3000);

await page.screenshot({
     path: `3.png`
});

console.log("登入成功");
複製程式碼

第四步:跟第一步一樣,點選立即購買按鈕,這裡會出現一個購買選擇浮層,然後我們點選立即支付之後需要載入米大師,故這裡我們延遲5000ms。

//點選購買
console.log("點選立即購買按鈕");
await page.tap(`.js_sale_buyalbum`);

await page.screenshot({
    path: `4.png`
});

console.log("點選支付浮層上的立即支付");
await page.tap(".js_buyalbum_pay");

await timeout(5000);
複製程式碼

第五步:在拉起米大師支付浮層之後,我們需要去點選提示中的確定按鈕,由於米大師是在iframe中開啟的,所以我們需要先獲取到我們當前頁frame,這個可以呼叫剛建立的頁面例項page的mainFrame()方法即可獲得,如果我們需要獲取子frame的話也只需要呼叫childFrames來進行獲取。在獲取到米大師對應的frame之後就可以呼叫midas_frame.$(selector)類jquery的方法進行元素的獲取,之後再模擬點選。

console.log("進入 米大師支付浮層")
await page.screenshot({
     path: `5.png`
});

let $frame = page.mainFrame();
let midas_frame = $frame.childFrames()[0];//獲取到midas對應的frame

console.log("點選確定 米大師支付浮層測試環境提示 的確認按鈕");
let $dom = await midas_frame.$(".fusion-pm-fl-wrapper .fpm-default");
await $dom.tap();

await page.screenshot({
    path: `6.png`
});
複製程式碼

第六步:點選Q幣支付

console.log("點選 米大師支付浮層 確認支付按鈕");
$dom = await midas_frame.$("#wrap .fpm-default");
await $dom.tap();

await timeout(5000);

await page.screenshot({
    path: `7.png`
});
複製程式碼

第七步:點選完成進入銘牌頁,測試完畢,關閉瀏覽器例項

console.log("點選 米大師支付浮層 支付完成");
$dom = await midas_frame.$("#wrap .btn-primary");
await $dom.tap();

await timeout(2000);

console.log("已購銘牌頁");
await page.screenshot({
     path: `8.png`
});
browser.close();
複製程式碼

最後在專案目錄中,我們看到,各個步驟的截圖都已生成。

體驗第二個demo,頁面效能檢測 Puppeteer Trace API

Trace API 主要是利用Chrome Performance,生成頁面效能追蹤的檔案 trace.json,在Chrome 開發者工具中上傳該檔案,就可以對裡面的火焰圖去做分析。
事例程式碼:

const puppeteer = require(`puppeteer`);
const devices = require(`puppeteer/DeviceDescriptors`);
const iPhone = devices[`iPhone 6`];

(async () => {
        const browser = await puppeteer.launch();

        const page = await browser.newPage();

        await page.emulate(iPhone);

        await page.tracing.start({path: `./trace.json`});
        await page.goto(`https://y.qq.com/m/digitalbum/gold/index.html?_video=true&id=2210323&g_f=tuijiannewupload#index/fans`);
        await page.tracing.stop();

        browser.close();
    } catch (e) {
        console.log(e.message);
    }
})();
複製程式碼

首先,這段程式碼執行的是模擬iphone6開啟林俊杰的《丹寧執著》數專售賣頁,並進行效能的分析。主要使用 tracing.start,stop生成trace.json檔案

trace.json

接下來我們開啟Chrome的開發者工具,進入到Performance欄目下,把剛才的trace.json拖上去就能看到資料了

總結

通過上面兩個例子,我們看到了puppeteer可以做UI自動化測試和頁面效能檢測,其實他的功能遠遠不止於此,比如還可以做爬蟲,去爬取github的文章或是掘金上的部落格,總之,自己也是初次嘗試,肯定會有更多的功能能夠被挖掘出來,希望大家多多交流。

相關閱讀

WebRTC 前端實時通訊技術
全面瞭解 React License
雲MongoDB優化讓LBS服務效能提升十倍

此文已由作者授權騰訊雲技術社群釋出,轉載請註明文章出處
原文連結:https://cloud.tencent.com/community/article/529168

相關文章