文:華為云DevCloud 樂(lè)少
1枷邪、背景
1.1 前端自動(dòng)化測(cè)試較少
前端瀏覽器眾多導(dǎo)致頁(yè)面兼容性問(wèn)題比較多错览,另外界面變化比較快棚贾,一個(gè)月內(nèi)可能頁(yè)面改版兩三次纲辽,這樣導(dǎo)致對(duì)前端自動(dòng)化測(cè)試較少,大家也不是很care您觉。18年英國(guó)的一位開(kāi)發(fā)者做過(guò)一些前端測(cè)試工具調(diào)查如圖1-1所示拙寡。從圖中可以發(fā)現(xiàn)有43%的用戶未使用過(guò)任何前端測(cè)試工具。
1.2 基于Puppteer的自動(dòng)化測(cè)試
Puppeteer(中文翻譯為“木偶”)是Google
Chrome團(tuán)隊(duì)官方的無(wú)界面(Headless)Chrome工具琳水。這是一個(gè)node庫(kù)肆糕。提供高級(jí)API來(lái)控制DevTools協(xié)議無(wú)頭版Chrome。Chrome的DevTools提供了非常之多和非常方便的頁(yè)面工具在孝,而Puppteteer則把這種能力通過(guò)Headless方式提供出來(lái)诚啃,可以在Linux操作能力,必將成為web應(yīng)用的自動(dòng)化測(cè)試行業(yè)標(biāo)桿私沮,場(chǎng)景非常之多始赎。
1.3 解決實(shí)際問(wèn)題
筆者是在華為云DevCloud的前端團(tuán)隊(duì),團(tuán)隊(duì)采用前端微服務(wù)架構(gòu)仔燕,也就是說(shuō)造垛,有很多前端portal,同時(shí)每個(gè)portal有若干個(gè)前端開(kāi)發(fā)進(jìn)行開(kāi)發(fā)維護(hù)晰搀,開(kāi)發(fā)之間溝通交流較少五辽,而且還是在異地進(jìn)行開(kāi)發(fā)。但每個(gè)服務(wù)同屬于DevCloud產(chǎn)品外恕,所以頁(yè)面體驗(yàn)杆逗、場(chǎng)景、控件鳞疲、術(shù)語(yǔ)都需要保持一致髓迎,如果通過(guò)人工的方式來(lái)對(duì)每個(gè)服務(wù)頁(yè)面進(jìn)行檢測(cè)是十分困難的一件工作。
2建丧、Puppeteer能做什么
可以這么說(shuō)排龄,在chrome瀏覽器手動(dòng)能完成的大部分事情可以使用puppteteer完成!你可以操作頁(yè)面的dom翎朱、抓取內(nèi)容等等橄维。另外puppeteer還可以:
生成頁(yè)面的截圖和PDF;
抓取SPA并生成預(yù)先呈現(xiàn)的內(nèi)容(SSR)
從網(wǎng)站上抓取你所想要的內(nèi)容拴曲。自動(dòng)表單提交争舞,UI測(cè)試,鍵盤輸入等等
創(chuàng)建一個(gè)最新的自動(dòng)化測(cè)試環(huán)境澈灼,使用最新的JavaScript和瀏覽器功能竞川,直接在最新版的chrome中運(yùn)行測(cè)試店溢。
3、Puppeteer版本
我最早使用的版本是puppetter@1.5.0版本委乌,通過(guò)npm i pupptetter下載床牧。里面包含自帶瀏覽器版本。如圖所示3-1所示遭贸。
在版本1.7.0之后戈咳,google把puppeteer拆成puppteteer-core和瀏覽器兩部分。也就是說(shuō)瀏覽器需要自己手動(dòng)去下載壕吹。下載地址可以通過(guò)華為云鏡像站搜索chromium進(jìn)行匹配下載著蛙,如圖3-2所示。
當(dāng)然不同的puppeteer-core版本匹配不同的瀏覽器版本耳贬,不然會(huì)有報(bào)錯(cuò)踏堡。版本匹配如圖2-3所示。大家也可以在官網(wǎng)github上進(jìn)行查看:https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md
4咒劲、 輕松入門
這部分包括windows和linux上的配置和運(yùn)行顷蟆。因?yàn)樽罱K是需要部署到linux服務(wù)上去。
4.1 簡(jiǎn)單實(shí)現(xiàn)
如果windows下使用puppeteer非常容易缎患,在package.json加上下面一行代碼:
"puppeteer-core":"1.13.0",
下面是一點(diǎn)簡(jiǎn)單截頻實(shí)現(xiàn):
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({path: 'example.png'});
await browser.close();
})();
4.2 基本語(yǔ)法
這些是puppeteer一些基礎(chǔ)的語(yǔ)法,可以滿足一些常用功能阎肝。
async/await
看官方的例子就可以看出來(lái)挤渔,幾乎所有的操作都是異步的,如果堅(jiān)持使用回調(diào)或者Promise.then 寫出來(lái)的代碼會(huì)非常丑陋且難讀风题,Puppeteer 官方推薦的也是使用高版本 Node 用 async/await 語(yǔ)法
async確保了函數(shù)返回一個(gè)promise判导,即使其中包含非promise。夠簡(jiǎn)單了吧沛硅?但是不僅僅只是如此眼刃,還有另一個(gè)關(guān)鍵詞await,只能在async函數(shù)里使用摇肌,同樣擂红,它也很cool。
關(guān)鍵詞await可以讓JavaScript進(jìn)行等待围小,直到一個(gè)promise執(zhí)行并返回它的結(jié)果昵骤,JavaScript才會(huì)繼續(xù)往下執(zhí)行。
let value = await promise
查找元素
這是 UI 自動(dòng)化測(cè)試最常用的功能了肯适,Puppeteer 的處理也相當(dāng)簡(jiǎn)單
page.$(selector)
page.$(selector)
這個(gè)在底層依然是執(zhí)行document.querySelector和document.querySelectorAll变秦。但返回的不是dom對(duì)象。而是封裝的框舔。
獲取DOM屬性
我們寫爬蟲(chóng)爬取頁(yè)面圖片列表蹦玫,感覺(jué)可以通過(guò)
page.$$(selector) 獲取到頁(yè)面的元素列表赎婚,然后再去轉(zhuǎn)成 DOM 對(duì)象,獲取 src樱溉,然后并不行挣输,想做對(duì)獲取元素對(duì)應(yīng) DOM
屬性的獲取,需要用專門的 API:page.$eval(selector, pageFunction[, ...args])
Evaluate
如果我們有一些及其個(gè)性的需求饺窿,無(wú)法通過(guò) page.$() 或者 page.$eval() 實(shí)現(xiàn)歧焦,可以用大招——evaluate。如下所示:
const result = await page.evaluate(() => {
return Promise.resolve(8 * 7);
});
console.log(result); // prints "56"
const aWindowHandle = await page.evaluateHandle(() => Promise.resolve(window));
aWindowHandle; // Handle for the window object. 相當(dāng)于把返回對(duì)象做了一層包裹
性能
通過(guò) page.getMetrics() 可以得到一些頁(yè)面性能數(shù)據(jù)肚医。
Timestamp The timestamp when the metrics sample was taken.
Documents 頁(yè)面文檔數(shù)
Frames 頁(yè)面 frame 數(shù)
JSEventListeners 頁(yè)面內(nèi)事件監(jiān)聽(tīng)器數(shù)
Nodes 頁(yè)面 DOM 節(jié)點(diǎn)數(shù)
LayoutCount 頁(yè)面 layout 數(shù)
RecalcStyleCount 樣式重算數(shù)
LayoutDuration 頁(yè)面 layout 時(shí)間
RecalcStyleDuration 樣式重算時(shí)長(zhǎng)
ScriptDuration script 時(shí)間
TaskDuration 所有瀏覽器任務(wù)時(shí)長(zhǎng)
JSHeapUsedSize JavaScript 占用堆大小
JSHeapTotalSize JavaScript 堆總量
會(huì)返回如下數(shù)據(jù):
{
Timestamp: 382305.912236,
Documents: 5,
Frames: 3,
JSEventListeners: 129,
Nodes: 8810,
LayoutCount: 38,
RecalcStyleCount: 56,
LayoutDuration: 0.596341000346001,
RecalcStyleDuration: 0.180430999898817,
ScriptDuration: 1.24401400075294,
TaskDuration: 2.21657899935963,
JSHeapUsedSize: 15430816,
JSHeapTotalSize: 23449600
}
更多功能請(qǐng)查看puppeteer的github官網(wǎng)绢馍。
https://github.com/GoogleChrome/puppeteer#usage
4.3 Linux安裝Puppeteer
windows下調(diào)試好的項(xiàng)目,在linux上運(yùn)行肠套,還是需要費(fèi)一番功夫舰涌,需要配置更多的參數(shù)。如下:
一你稚、下載相關(guān)依賴包瓷耙,這些依賴包都是chrome運(yùn)行所需要的。
yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64
libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64
alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 ipa-gothic-fonts xorg-x11-fonts-100dpi
xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc
二刁赖、字體安裝:
yum install ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc
三搁痛、增加—no-sandbox –disable-setuid-sandbox
const browser = await puppeteer.launch({args:['--no-sandbox', '--disable-setuid-sandbox']})
筆者的工作環(huán)境比較復(fù)雜,中間因?yàn)闄?quán)限問(wèn)題導(dǎo)致運(yùn)行報(bào)錯(cuò)宇弛,這個(gè)時(shí)候需要增加一些代理設(shè)置鸡典。
5、puppeteer體驗(yàn)度量實(shí)踐
前面主要是講一些puppeteer基本功能和實(shí)踐枪芒。那我們基于puppeteer怎么解決實(shí)際問(wèn)題的呢彻况。
5.1 規(guī)范的建立
在使用puppeteer之前,需要先梳理各微服務(wù)使用的場(chǎng)景舅踪,以及術(shù)語(yǔ)規(guī)范等纽甘,梳理清楚之后在來(lái)進(jìn)行工具自動(dòng)化。首先我們參照尼爾森可用性原則抽碌。
上面這位略顯陰柔的帥哥就是尼爾森(Jakob Nielsen)悍赢,人機(jī)交互學(xué)博士。他通過(guò)自己的郵件列表以及網(wǎng)站货徙,向成千上萬(wàn)的web設(shè)計(jì)師傳授web易用性方面的只是泽裳。是web設(shè)計(jì)師眼中的頂尖領(lǐng)袖。Jakob
Nielsen在1995年發(fā)表了“尼爾森十大可用性原則”破婆。
在尼爾森十大原則里有一項(xiàng)是UI一致性原則涮总,我們基于這個(gè)梳理出DevCloud的一些細(xì)化的點(diǎn),并給出每個(gè)測(cè)試因子的權(quán)重和分值祷舀,計(jì)算出各個(gè)服務(wù)的UI體驗(yàn)瀑梗,最后換算成百分值烹笔,最后加權(quán)計(jì)算服務(wù)體驗(yàn)總分。圖5-1就是我們梳理出來(lái)的部分規(guī)則抛丽。
5.2 具體使用puppteer
在上面建立規(guī)則之后谤职,我們?cè)籴槍?duì)每個(gè)檢測(cè)項(xiàng)評(píng)估是否可以量化,怎么量化亿鲜。比如我們想檢測(cè)組件的覆蓋度允蜈。圖4-2是我們產(chǎn)品所使用的公共組件庫(kù)。都是以ave-開(kāi)頭蒿柳,checkbox的命名就是ave-button饶套。那普通的checkbox則是以input[type=checkbox]來(lái)寫的。我們針對(duì)每個(gè)服務(wù)去掃面線上各個(gè)頁(yè)面垒探,看使用ave-check和使用原生input
checkbox的數(shù)量妓蛮,這樣就能統(tǒng)計(jì)出組件庫(kù)的覆蓋度。最終驅(qū)動(dòng)各服務(wù)去整改圾叼。
通過(guò)組件的形式使得各個(gè)服務(wù)體驗(yàn)基本一致蛤克。
最終通過(guò)圖表的形式來(lái)進(jìn)行展示。如圖5-3所示夷蚊。
從圖上我們可以看到ave-checkbox得到整改构挤。
通過(guò)以上的方式,我們可以在組件惕鼓、樣式筋现、以及體驗(yàn)旅程方面都能很好的把握整個(gè)產(chǎn)品設(shè)計(jì)是否與我們預(yù)期是一致的。
我們團(tuán)隊(duì)在自動(dòng)化方面一直在探索呜笑,除了在前端測(cè)試夫否、接口測(cè)試以及編譯構(gòu)建方面也一直遵從能夠使用工具提升效率彻犁,絕不靠人工來(lái)進(jìn)行檢測(cè)的理念叫胁,不斷的實(shí)踐,極大的減少了人力成本汞幢。當(dāng)然這些能力也一直是對(duì)外開(kāi)放的:華為云軟件開(kāi)發(fā)服務(wù)DevCloud驼鹅。也歡迎大家來(lái)建議和探討。
???????6森篷、 參考資料及擴(kuò)展閱讀材料
The Front-End Tooling Survey 2018 - Results
尼爾森可用性十大原則
http://www.reibang.com/p/53daaa5ba794
華為云DevCloud作為一站式云端DevOps平臺(tái)输钩,集成華為近30年研發(fā)實(shí)踐和前沿理念,面向開(kāi)發(fā)者提供研發(fā)工具服務(wù)仲智,讓軟件開(kāi)發(fā)簡(jiǎn)單高效÷蚰耍現(xiàn)支持5人以下額度范圍內(nèi),可以免費(fèi)使用钓辆,并且可以預(yù)約免費(fèi)的產(chǎn)品演示和技術(shù)交流剪验,詳情查看華為云官網(wǎng)