在前面不少文章中,咱們都介紹了單元測試。若是你瞭解單元測試,或者讀過我以前寫的單元測試的文章,那麼你必定知道,單元測試的測試對象是單獨的、隔離的小代碼片斷或者代碼單元。與單元測試不一樣,端對端測試的測試對象則是頁面上的用戶交互,咱們對底層實現一無所知,也就是說咱們的測試是黑盒的。另外,一些跨頁測試,好比連接檢查,登錄跳轉等功能必須使用端對端測試才能檢查出來,單元測試是沒法測這些功能的。之前我只寫單元測試,不寫端對端測試,結果有一次所負責的頁面上有個連接不能點了,還好及時修復,但仍是讓我感覺到了端對端測試,或者說是自動化端對端測試的重要性。git
Puppeteer 默認狀況下,全部操做是不可見的,若是你想像我這樣監視發生的一切,須要將 Puppeteer 的
headless
選項設爲false。
github
我使用過不少端對端測試的輪子,好比 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(); })();
將上述代碼寫進 Node 腳本中,並運行就能夠了!看下生成的截圖:babel
是否是很簡單?短短几行代碼就作了這麼多事。若是你對 async
、await
這種語法不熟悉,那麼我強烈建議你去學習一下,這種語法在 Puppeteer 中使用率簡直不要過高。不過也不要擔憂學習成本, async
、await
語法很是簡單,就是 Promise 的一種新寫法而已,讓你的異步代碼看起來就像是同步的同樣。less
要知道,Puppeteer 是一個瀏覽器自動化工具,它只能進行瀏覽器的自動化,自己並不具備測試功能。我說的測試功能指的是,斷言啊,生成測試報告啊這些功能。若是你不熟悉這些概念,那麼請移步:《Jest 單元測試入門》。因此,除了 Puppeteer 外,咱們還須要使用一個測試工具,我選擇了 Jest,理由在以前的博文中已經說過不少遍了,這裏再也不贅述。使用 Jest 很是簡單,只須要異步
具體用法看以前的博文:《Jest 單元測試入門》。async
講完了 Puppeteer 和 Jest 的基本用法,咱們來看一下,如何將二者結合起來使用。其實將 Jest 與 Puppeteer 結合使用很是簡單,由於 Puppeteer 的本質就是個 NPM 模塊而已,因此咱們只須要在 Jest 測試腳本中引入它便可使用了。爲什麼如此呢?由於測試腳本的本質其實也是 Node 腳本,既然是 Node 腳本那麼固然能夠直接引入 NPM 模塊來用了!函數
須要注意的是,由於 Puppeteer 一般須要使用
async
、await
這種語法,若是你的 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 節點中的文本等。