Puppeteer 初探之前端自動化測試
初識puppeteer
puppeteer 翻譯是操縱木偶的人,利用這個工具,我們能做一個操縱頁面的人。puppeteer是一個nodejs的庫,支援呼叫Chrome的API來操縱Web,相比較Selenium或是PhantomJs,它最大的特點就是它的操作Dom可以完全在記憶體中進行模擬既在V8引擎中處理而不開啟瀏覽器,而且關鍵是這個是Chrome團隊在維護,會擁有更好的相容性和前景。 PS :有興趣的加入Android工程師交流QQ群:752016839 主要針對Android開發人員提升自己,突破瓶頸,相信你來學習,會有提升和收穫。
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();
})();
複製程式碼
這段程式碼會開啟
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的文章或是掘金上的部落格,總之,自己也是初次嘗試,肯定會有更多的功能能夠被挖掘出來,希望大家多多交流。