使用 Jest 與 Puppeteer 來進行界面自動化測試

UI自動化測試 vs. 單元測試

在前面不少文章中,咱們都介紹了單元測試。若是你瞭解單元測試,或者讀過我以前寫的單元測試的文章,那麼你必定知道,單元測試的測試對象是單獨的、隔離的小代碼片斷或者代碼單元。與單元測試不一樣,端對端測試的測試對象則是頁面上的用戶交互,咱們對底層實現一無所知,也就是說咱們的測試是黑盒的。另外,一些跨頁測試,好比連接檢查,登錄跳轉等功能必須使用端對端測試才能檢查出來,單元測試是沒法測這些功能的。之前我只寫單元測試,不寫端對端測試,結果有一次所負責的頁面上有個連接不能點了,還好及時修復,但仍是讓我感覺到了端對端測試,或者說是自動化端對端測試的重要性。git

Puppeteer 默認狀況下,全部操做是不可見的,若是你想像我這樣監視發生的一切,須要將 Puppeteer 的 headless 選項設爲 false。github

使用 Puppeteer 進行瀏覽器自動化

我使用過不少端對端測試的輪子,好比 Selenium、Appium、Protractor、Zombie.js、Cypress、Nightmare、Puppeteer 等。但最終仍是選擇了 Puppeteer,由於 Selenium 和 Appium 太難用了,Protractor 則像是專門給 Angular 設計的,Zombie.js 太簡單了,並且使用的瀏覽器內核不是市面上流行的任何一個,而是自定義的。Cypress 有平臺依賴,我只是想要個本地運行的工具而已。只剩 Nightmare 和 Puppeteer 了,其實這兩個都是好選擇,可是我是個 star 控,Puppeteer 的 star 比 Nightmare 多,因此我選擇了 Puppeteer。但事實上 Nightmare 更流行,由於我發現螞蟻最新的那個 Antd Pro 就是用的 Nightmare,阿里一些其餘端對端測試的工具也有基於 Nightmare 來作的。因此若是你想使用 Nightmare 來進行自動化端對端測試也是徹底沒有問題的。npm

使用 Puppeteer 很是簡單,首先安裝它:json

yarn add puppeteer
# or "npm i puppeteer"

const puppeteer = require('puppeteer');而後就能夠在 Node 腳本中使用它了!來個簡單的導航並截屏例子吧!這個例子先啓動瀏覽器,導航到 https://baidu.com 頁面,而後截屏並保存爲 baidu.png,最後關閉瀏覽器。瀏覽器

 
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://baidu.com');
await page.screenshot({path: 'baidu.png'});
 
await browser.close();
})();

  

image將上述代碼寫進 Node 腳本中,並運行就能夠了!看下生成的截圖:babel

是否是很簡單?短短几行代碼就作了這麼多事。若是你對 asyncawait 這種語法不熟悉,那麼我強烈建議你去學習一下,這種語法在 Puppeteer 中使用率簡直不要過高。不過也不要擔憂學習成本, asyncawait 語法很是簡單,就是 Promise 的一種新寫法而已,讓你的異步代碼看起來就像是同步的同樣。less

使用 Jest 來進行測試

要知道,Puppeteer 是一個瀏覽器自動化工具,它只能進行瀏覽器的自動化,自己並不具備測試功能。我說的測試功能指的是,斷言啊,生成測試報告啊這些功能。若是你不熟悉這些概念,那麼請移步:《Jest 單元測試入門》。因此,除了 Puppeteer 外,咱們還須要使用一個測試工具,我選擇了 Jest,理由在以前的博文中已經說過不少遍了,這裏再也不贅述。使用 Jest 很是簡單,只須要異步

  • 安裝 Jest
  • 編寫測試腳本 *.test.js
  • 最後在終端中輸入 jest 命令運行測試

具體用法看以前的博文:《Jest 單元測試入門》。async

將 Jest 與 Puppeteer 結合使用

講完了 Puppeteer 和 Jest 的基本用法,咱們來看一下,如何將二者結合起來使用。其實將 Jest 與 Puppeteer 結合使用很是簡單,由於 Puppeteer 的本質就是個 NPM 模塊而已,因此咱們只須要在 Jest 測試腳本中引入它便可使用了。爲什麼如此呢?由於測試腳本的本質其實也是 Node 腳本,既然是 Node 腳本那麼固然能夠直接引入 NPM 模塊來用了!函數

須要注意的是,由於 Puppeteer 一般須要使用 asyncawait 這種語法,若是你的 Node 版本在7.6及以上,那麼恭喜你,直接大膽使用,不然須要在 Jest 中配置 Babel,來使其支持這種新語法。在 Jest 中配置 Babel 很是簡單,你能夠在這裏找到具體方法。

讓咱們來個小例子吧!首先,咱們打開百度頁面,並斷言百度頁面的 title 是 百度一下,你就知道。那麼測試腳本應該這麼寫:

const puppeteer = require('puppeteer');
 
test('baidu title is correct', async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://baidu.com');
const title = await page.title();
expect(title).toBe('百度一下,你就知道');
await browser.close();
});

$ npm test看到 test 和 expect 兩個全局函數了嗎?這就是 Jest 所賦予的能力,讓你能夠編寫測試用例和斷言。最後在命令行輸入 npm test,即 jest(這是在 package.json 中配置好的命令),便可看到生成的測試報告:

 
> fe-test@1.0.0 test /Users/liuyiqi/code/fe-test
> jest
 
PASS puppeteer-demo/baidu-title.test.js
PASS puppeteer-demo/screenshot.test.js
 
Test Suites: 2 passed, 2 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 3.241s
Ran all test suites.

  

https://github.com/lewis617/fe-test/tree/master/puppeteer-demo其中 screenshot.test.js 是截屏的那個例子,baidu-title.test.js 是斷言百度首頁 title 的例子。你能夠在這裏找到源碼:

至此,使用 Jest 與 Puppeteer 來進行端對端測試的基本用法就講完了。下篇博文咱們將會集中講解經常使用 Puppeteer 功能,好比模擬用戶輸入、執行 JavaScript 腳本、獲取某個 DOM 節點中的文本等。

相關文章
相關標籤/搜索