欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Puppeteer前端自動(dòng)化測(cè)試實(shí)踐

 更新時(shí)間:2019年02月21日 09:27:02   作者:Athon  
這篇文章主要介紹了詳解Puppeteer前端自動(dòng)化測(cè)試實(shí)踐,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

起因

目前我們?cè)诔掷m(xù)開(kāi)發(fā)著一個(gè)幾十個(gè)頁(yè)面,十萬(wàn)+行代碼的項(xiàng)目,隨著產(chǎn)品的更迭,總會(huì)出現(xiàn)這樣的問(wèn)題。在對(duì)某些業(yè)務(wù)邏輯或者功能進(jìn)行添加或者修改的時(shí)候(尤其是通用邏輯),這些通用的邏輯或者組件往往會(huì)牽扯到一些其他地方的問(wèn)題。由于測(cè)試人員受限,我們很難在完成一個(gè)模塊單元后,對(duì)所有功能重新測(cè)試一遍。
同時(shí),由于環(huán)境及數(shù)據(jù)的區(qū)別,(以及在開(kāi)發(fā)過(guò)程中對(duì)代碼完備性的疏忽),代碼會(huì)在某些特殊數(shù)據(jù)的解析和和展示上出現(xiàn)問(wèn)題,在開(kāi)發(fā)和測(cè)試中很難去發(fā)現(xiàn)??偟膩?lái)說(shuō),我們希望有一個(gè)這樣的工具,幫我們解決上述幾個(gè)問(wèn)題:

  1. 在進(jìn)行代碼和功能改動(dòng)后,能夠自動(dòng)訪(fǎng)問(wèn)各個(gè)功能的頁(yè)面,檢測(cè)問(wèn)題
  2. 針對(duì)大量的數(shù)據(jù)內(nèi)容,進(jìn)行批量訪(fǎng)問(wèn),檢測(cè)對(duì)于不同數(shù)據(jù)的展示是否存在問(wèn)題
  3. 測(cè)試與代碼功能盡量不耦合,避免每次上新功能都需要對(duì)測(cè)試用例進(jìn)行修改,維護(hù)成本太大
  4. 定期的測(cè)試任務(wù),及時(shí)發(fā)現(xiàn)數(shù)據(jù)平臺(tái)針對(duì)新數(shù)據(jù)的展示完備性

其中,最重要的問(wèn)題,就是將測(cè)試代碼與功能解耦,避免每次迭代和修改都需要追加新的測(cè)試用例。我們?nèi)绾巫龅竭@一點(diǎn)呢?首先我們來(lái)梳理下測(cè)試平臺(tái)的功能。

功能設(shè)定

由于我們的平臺(tái)主要是進(jìn)行數(shù)據(jù)展示,所以我們?cè)跍y(cè)試過(guò)程中,主要以日常的展示數(shù)據(jù)為重心即可,針對(duì)一些復(fù)雜的表單操作先不予處理。針對(duì)上述的幾個(gè)問(wèn)題,我們針對(duì)自動(dòng)化測(cè)試工具的功能如下:

  1. 依次訪(fǎng)問(wèn)各個(gè)頁(yè)面
  2. 訪(fǎng)問(wèn)各個(gè)頁(yè)面的具體內(nèi)容,如時(shí)間切換、選項(xiàng)卡切換、分頁(yè)切換、表格展開(kāi)行等等
  3. 針對(duì)數(shù)據(jù)表格中的詳情鏈接,選擇前100條進(jìn)行訪(fǎng)問(wèn),并進(jìn)行下鉆頁(yè)的繼續(xù)測(cè)試
  4. 捕獲在頁(yè)面中的錯(cuò)誤請(qǐng)求
  5. 對(duì)錯(cuò)誤信息進(jìn)行捕獲,統(tǒng)計(jì)和上報(bào)

根據(jù)以上的梳理,我們可以把整個(gè)應(yīng)用分為幾個(gè)測(cè)試單元

  • 頁(yè)面單元,檢測(cè)各功能頁(yè)面訪(fǎng)問(wèn)的穩(wěn)定性
  • 詳情頁(yè)單元,根據(jù)頁(yè)面的數(shù)據(jù)列表,進(jìn)行批量的詳情頁(yè)跳轉(zhuǎn),檢測(cè)不同參數(shù)下詳情頁(yè)的穩(wěn)定性
  • 功能單元,用于檢測(cè)頁(yè)面和詳情頁(yè)各種展示類(lèi)型點(diǎn)擊切換后是否產(chǎn)生錯(cuò)誤

通過(guò)這樣的劃分,我們針對(duì)各個(gè)單元進(jìn)行具體的測(cè)試邏輯書(shū)寫(xiě)用例,這樣就可以避免再添加新功能和頁(yè)面時(shí),頻繁對(duì)測(cè)試用例進(jìn)行修改了。

Puppeteer

帶著上面我們的需求,我們來(lái)看下Puppeteer的功能和特性,是否能夠滿(mǎn)足我們的要求。

文檔地址

Puppeteer是一個(gè)Node庫(kù),它提供了一個(gè)高級(jí) API 來(lái)通過(guò) DevTools 協(xié)議控制 Chromium 或 Chrome。Puppeteer 默認(rèn)以 headless 模式運(yùn)行,但是可以通過(guò)修改配置文件運(yùn)行“有頭”模式。

我們可以使用Puppeteer完成以下工作:

  • 訪(fǎng)問(wèn)頁(yè)面,進(jìn)行截圖
  • 自動(dòng)進(jìn)行鍵盤(pán)輸入,提交表單
  • 模擬點(diǎn)擊等用戶(hù)操作
  • 等等等等。。

我們來(lái)通過(guò)一些小案例,來(lái)介紹他們的基本功能:

訪(fǎng)問(wèn)一個(gè)帶有ba認(rèn)證的網(wǎng)站

puppeteer可以創(chuàng)建page實(shí)例,并使用goto方法進(jìn)行頁(yè)面訪(fǎng)問(wèn),page包含一系列方法,可以對(duì)頁(yè)面進(jìn)行各種操作。

(async () => {
 const browser = await puppeteer.launch();
 const page = await browser.newPage();
 // ba認(rèn)證
 await page.authenticate({
  username,
  password
 });
 // 訪(fǎng)問(wèn)頁(yè)面
 await page.goto('https://example.com');
 // 進(jìn)行截圖
 await page.screenshot({path: 'example.png'});

 await browser.close();
})();

訪(fǎng)問(wèn)登陸頁(yè)面,并進(jìn)行登錄

首先,對(duì)于SPA(單頁(yè)面應(yīng)用),我們都知道,當(dāng)頁(yè)面進(jìn)入后,客戶(hù)端代碼才開(kāi)始進(jìn)行渲染工作。我們需要等到頁(yè)面內(nèi)容渲染完成后,再進(jìn)行對(duì)應(yīng)的操作。我們有以下幾種方法來(lái)使用

waitUntil

puppeteer針對(duì)頁(yè)面的訪(fǎng)問(wèn),切換等,提供了waitUntil參數(shù),來(lái)確定滿(mǎn)足什么條件才認(rèn)為頁(yè)面跳轉(zhuǎn)完成。包括以下事件:

  • load - 頁(yè)面的load事件觸發(fā)時(shí)
  • domcontentloaded - 頁(yè)面的DOMContentLoaded事件觸發(fā)時(shí)
  • networkidle0 - 不再有網(wǎng)絡(luò)連接時(shí)觸發(fā)(至少500毫秒后)
  • networkidle2 - 只有2個(gè)網(wǎng)絡(luò)連接時(shí)觸發(fā)(至少500毫秒后)

通過(guò)waitUnitl,我們可以當(dāng)頁(yè)面請(qǐng)求都完成之后,確定頁(yè)面已經(jīng)訪(fǎng)問(wèn)完成。

waitFor

waitFor方法可以在指定動(dòng)作完成后才進(jìn)行resolve

// wait for selector
await page.waitFor('.foo');
// wait for 1 second
await page.waitFor(1000);
// wait for predicate
await page.waitFor(() => !!document.querySelector('.foo'));

我們可以利用waitForSelector方法,當(dāng)?shù)卿浛蜾秩境晒?,才進(jìn)行登錄操作

// 等待密碼輸入框渲染
await page.waitFor('#password');
// 輸入用戶(hù)名
await page.type('input#username', "username");
// 輸入密碼
await page.type('input#password', "testpass");

// 點(diǎn)擊登錄按鈕
await Promise.all([
 page.waitForNavigation(), // 等跳轉(zhuǎn)完成后resolve
 page.click('button.login-button'), // 點(diǎn)擊該鏈接將間接導(dǎo)致導(dǎo)航(跳轉(zhuǎn))
]);

await page.waitFor(2000)

// 獲取cookies
const cookies = await page.cookies()

針對(duì)列表內(nèi)容里的鏈接進(jìn)行批量訪(fǎng)問(wèn)

主要利用到page實(shí)例的選擇器功能

const table = await page.$('.table')
const links = await table.$$eval('a.link-detail', links =>
 links.map(link => link.href)
);

// 循環(huán)訪(fǎng)問(wèn)links
...

進(jìn)行錯(cuò)誤和訪(fǎng)問(wèn)監(jiān)聽(tīng)

puppeteer可以監(jiān)聽(tīng)在頁(yè)面訪(fǎng)問(wèn)過(guò)程中的報(bào)錯(cuò),請(qǐng)求等等,這樣我們就可以捕獲到頁(yè)面的訪(fǎng)問(wèn)錯(cuò)誤并進(jìn)行上報(bào)啦,這也是我們進(jìn)行測(cè)試需要的基本功能~

// 當(dāng)發(fā)生頁(yè)面js代碼沒(méi)有捕獲的異常時(shí)觸發(fā)。
page.on('pagerror', () => {})
// 當(dāng)頁(yè)面崩潰時(shí)觸發(fā)。
page.on('error', () => {})
// 當(dāng)頁(yè)面發(fā)送一個(gè)請(qǐng)求時(shí)觸發(fā)
page.on('request')
// 當(dāng)頁(yè)面的某個(gè)請(qǐng)求接收到對(duì)應(yīng)的 response 時(shí)觸發(fā)。
page.on('response')

通過(guò)以上的幾個(gè)小案例,我們發(fā)現(xiàn)Puppeteer的功能非常強(qiáng)大,完全能夠滿(mǎn)足我們以上的對(duì)頁(yè)面進(jìn)行自動(dòng)訪(fǎng)問(wèn)的需求。接下來(lái),我們針對(duì)我們的測(cè)試單元進(jìn)行個(gè)單元用例的書(shū)寫(xiě)

最終功能

通過(guò)我們上面對(duì)測(cè)試單元的規(guī)劃,我們可以規(guī)劃一下我們的測(cè)試路徑

訪(fǎng)問(wèn)網(wǎng)站 -> 登陸 -> 訪(fǎng)問(wèn)頁(yè)面1 -> 進(jìn)行基本單元測(cè)試 -> 獲取詳情頁(yè)跳轉(zhuǎn)鏈接 -> 依次訪(fǎng)問(wèn)詳情頁(yè) -> 進(jìn)行基本單元測(cè)試

-> 訪(fǎng)問(wèn)頁(yè)面2 ...

所以,我們可以拆分出幾個(gè)大類(lèi),和幾個(gè)測(cè)試單元,來(lái)進(jìn)行各項(xiàng)測(cè)試

// 包含基本的測(cè)試方法,log輸出等
class Base {}

// 詳情頁(yè)單元,進(jìn)行一些基本的單元測(cè)試
class PageDetal extends Base {}

// 頁(yè)面單元,進(jìn)行基本的單元測(cè)試,并獲取并依次訪(fǎng)問(wèn)詳情頁(yè)
class Page extends PageDetal {}

// 進(jìn)行登錄等操作,并依次訪(fǎng)問(wèn)頁(yè)面單元進(jìn)行測(cè)試
class Root extends Base {}

同時(shí),我們?nèi)绾卧诠δ茼?yè)面變化時(shí),跟蹤到測(cè)試的變化呢,我們可以針對(duì)我們測(cè)試的功能,為其添加自定義標(biāo)簽test-role,測(cè)試時(shí),根據(jù)自定義標(biāo)簽進(jìn)行測(cè)試邏輯的編寫(xiě)。

例如針對(duì)時(shí)間切換單元,我們做一下簡(jiǎn)單的介紹:

// 1. 獲取測(cè)試單元的元素
const timeSwitch = await page.$('[test-role="time-switch"]');

// 若頁(yè)面沒(méi)有timeSwitch, 則不用進(jìn)行測(cè)試
if (!timeSwitch) return

// 2. time switch的切換按鈕
const buttons = timeSwitch.$$('.time-switch-button')

// 3. 對(duì)按鈕進(jìn)行循環(huán)點(diǎn)擊
for (let i = 0; i < buttons.length; i++) {
 const button = buttons[i]

 // 點(diǎn)擊按鈕
 await button.click()

 // 重點(diǎn)! 等待對(duì)應(yīng)的內(nèi)容出現(xiàn)時(shí),才認(rèn)定頁(yè)面訪(fǎng)問(wèn)成功
 try {
  await page.waitFor('[test-role="time-switch-content"]')
 } catch (error) {
  reportError (error)
 }

 // 截圖
 await page.screenshot()
}

上面只是進(jìn)行了一個(gè)簡(jiǎn)單的訪(fǎng)問(wèn)內(nèi)容測(cè)試,我們可以根據(jù)我們的用例單元書(shū)寫(xiě)各自的測(cè)試邏輯,在我們?nèi)粘i_(kāi)發(fā)時(shí),只需要對(duì)需要測(cè)試的內(nèi)容,加上對(duì)應(yīng)的test-role即可。

總結(jié)

根據(jù)以上的功能劃分,我們很好的將一整個(gè)應(yīng)用拆分成各個(gè)測(cè)試單元進(jìn)行單元測(cè)試。需要注意的是,我們目前僅僅是對(duì)頁(yè)面的可訪(fǎng)問(wèn)性進(jìn)行測(cè)試,僅僅驗(yàn)證當(dāng)用戶(hù)進(jìn)行各種操作,訪(fǎng)問(wèn)各個(gè)頁(yè)面單元時(shí)頁(yè)面是否會(huì)出錯(cuò)。并沒(méi)有對(duì)頁(yè)面的具體展示效果進(jìn)行測(cè)試,這樣會(huì)和頁(yè)面的功能內(nèi)容耦合起來(lái),就需要單獨(dú)的測(cè)試用例的編寫(xiě)了。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • node下使用UglifyJS壓縮合并JS文件的方法

    node下使用UglifyJS壓縮合并JS文件的方法

    下面小編就為大家分享一篇node下使用UglifyJS壓縮合并JS文件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • 解決npm?run?serve啟動(dòng)報(bào)錯(cuò)npm?ERR?Missing?script:"serve"

    解決npm?run?serve啟動(dòng)報(bào)錯(cuò)npm?ERR?Missing?script:"serve&q

    這篇文章主要給大家介紹了關(guān)于解決npm?run?serve啟動(dòng)報(bào)錯(cuò)npm?ERR?Missing?script:"serve"的相關(guān)資料,這是最近開(kāi)發(fā)中遇到的一個(gè)問(wèn)題,文中通過(guò)圖文將解決辦法介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • Koa2微信公眾號(hào)開(kāi)發(fā)之消息管理

    Koa2微信公眾號(hào)開(kāi)發(fā)之消息管理

    這篇文章主要介紹了Koa2微信公眾號(hào)開(kāi)發(fā)之消息管理,這一節(jié)我們就來(lái)看看公眾號(hào)的消息管理。并實(shí)現(xiàn)一個(gè)自動(dòng)回復(fù)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • Nest.js Controller路由和請(qǐng)求處理強(qiáng)大功能解析

    Nest.js Controller路由和請(qǐng)求處理強(qiáng)大功能解析

    這篇文章主要為大家,介紹了Nest.js Controller路由和請(qǐng)求處理強(qiáng)大功能解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • node中如何使用redis的實(shí)現(xiàn)

    node中如何使用redis的實(shí)現(xiàn)

    本文主要介紹了node中如何使用redis的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • nodejs實(shí)現(xiàn)文件或文件夾上傳功能的代碼示例

    nodejs實(shí)現(xiàn)文件或文件夾上傳功能的代碼示例

    在平常的工作中,經(jīng)常會(huì)遇到需要將本地項(xiàng)目文件同步到遠(yuǎn)端服務(wù)器的情況,所以每次遇到都需要考慮如何將文件上傳到服務(wù)器上,所以本文就給大家介紹一下nodejs實(shí)現(xiàn)文件或文件夾上傳功能,需要的朋友可以參考下
    2023-08-08
  • node.js中的fs.lchownSync方法使用說(shuō)明

    node.js中的fs.lchownSync方法使用說(shuō)明

    這篇文章主要介紹了node.js中的fs.lchownSync方法使用說(shuō)明,本文介紹了fs.lchownSync的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • 基于Express和Multer實(shí)現(xiàn)文件本地服務(wù)器文件上傳功能

    基于Express和Multer實(shí)現(xiàn)文件本地服務(wù)器文件上傳功能

    在現(xiàn)代應(yīng)用程序中,文件上傳功能成為了用戶(hù)共享和存儲(chǔ)數(shù)據(jù)的重要途徑,所以本文我們一起來(lái)探討文件上傳中間件的重要性,并提供常見(jiàn)的實(shí)現(xiàn)方法和相應(yīng)的代碼吧
    2023-06-06
  • nodejs構(gòu)建本地web測(cè)試服務(wù)器 如何解決訪(fǎng)問(wèn)靜態(tài)資源問(wèn)題

    nodejs構(gòu)建本地web測(cè)試服務(wù)器 如何解決訪(fǎng)問(wèn)靜態(tài)資源問(wèn)題

    這篇文章主要為大家詳細(xì)介紹了nodejs構(gòu)建本地web測(cè)試服務(wù)器,教大家如何解決訪(fǎng)問(wèn)靜態(tài)資源問(wèn)題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 使用Redis和Node.js來(lái)開(kāi)發(fā)簡(jiǎn)單的實(shí)時(shí)聊天功能

    使用Redis和Node.js來(lái)開(kāi)發(fā)簡(jiǎn)單的實(shí)時(shí)聊天功能

    在眾多實(shí)時(shí)通信的技術(shù)中,Redis和Node.js的結(jié)合是一種非常強(qiáng)大和流行的選擇,Redis是一種高性能的鍵值存儲(chǔ)數(shù)據(jù)庫(kù),而Node.js是一個(gè)基于事件驅(qū)動(dòng)的JavaScript運(yùn)行時(shí)環(huán)境,兩者的結(jié)合可以輕松實(shí)現(xiàn)實(shí)時(shí)聊天功能,本文將指導(dǎo)您使用Redis和Node.js來(lái)開(kāi)發(fā)一個(gè)簡(jiǎn)單的實(shí)時(shí)聊天功能
    2024-08-08

最新評(píng)論