1. 程式人生 > >Puppeteer 初探之前端自動化測試

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();
})();
複製程式碼

這段程式碼會開啟

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的文章或是掘金上的部落格,總之,自己也是初次嘗試,肯定會有更多的功能能夠被挖掘出來,希望大家多多交流。