本文為實(shí)踐的產(chǎn)物,總結(jié)從搭建到使用過(guò)程中遇到的問(wèn)題,初學(xué)者可以參考。
- Jest 和 Enzyme 的基本介紹
- 測(cè)試環(huán)境搭建
- 測(cè)試腳本編寫(xiě)
- 運(yùn)行并調(diào)試
- 匹配器使用
- 測(cè)試異步代碼
- 遇到的問(wèn)題
- 參考資料
Jest、Enzyme介紹
Jest是Facebook發(fā)布的一個(gè)開(kāi)源的、基于Jasmine框架的JavaScript單元測(cè)試工具,支持?jǐn)嘌浴⒎抡妗⒖煺諟y(cè)試、測(cè)試覆蓋率報(bào)告等。
Enzyme獲得React 官方的推薦,Airbnb開(kāi)源的React測(cè)試類庫(kù)Enzyme提供了一套簡(jiǎn)介強(qiáng)大的API,并通過(guò)jQuery風(fēng)格的方式進(jìn)行DOM處理,開(kāi)發(fā)體檢十分友好。
強(qiáng)烈推薦閱讀使用jest+enzyme進(jìn)行react項(xiàng)目測(cè)試 - 介紹篇
測(cè)試環(huán)境搭建
在開(kāi)發(fā)React應(yīng)用的基礎(chǔ)上,需要安裝Jest、Enzyme以及對(duì)應(yīng)的babel-jest。
使用 yarn
安裝 Jest︰
yarn add --dev jest enzyme babel-jest
或 npm
:
npm install --save-dev jest enzyme babel-jest
將下面的配置部分添加到package.json 里面:
{
"scripts": {
"test": "jest"
}
"jest": {
"moduleFileExtensions": [
"js",
"jsx"
],
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
".*\\.(css|less|scss)$": "<rootDir>/__mocks__/styleMock.js"
},
"transform": {
"^.+\\.js$": "babel-jest"
}
},
}
- moduleFileExtensions:代表支持加載的文件名,與Webpack中的resolve.extensions類似
- moduleNameMapper:代表需要被Mock的資源名稱。如果需要Mock靜態(tài)資源(如less、scss等),需要配置Mock的路徑<rootDir>/mocks/xxMock.js
- transform:用于編譯 ES6/ES7 語(yǔ)法,需配合 babel-jest使用
這三個(gè)是常用的配置,更多 Jest 配置見(jiàn)官方文檔:Jest Configuration
然后,創(chuàng)建xx.test.js的文件,寫(xiě)實(shí)際的測(cè)試邏輯
最后,運(yùn)行yarn test
測(cè)試腳本編寫(xiě)
強(qiáng)烈推薦閱讀使用jest+enzyme進(jìn)行react項(xiàng)目測(cè)試 - 測(cè)試手法篇
測(cè)試用例寫(xiě)法總結(jié)
組件UI測(cè)試用snapshot
snapshot可以測(cè)試到組件的渲染結(jié)果是否符合預(yù)期,預(yù)期就是指你上一次錄入保存的結(jié)果,toMatchSnapshot方法會(huì)去幫你對(duì)比這次將要生成的結(jié)構(gòu)與上次的區(qū)別
需要注意的是一個(gè)足夠健壯的測(cè)試應(yīng)該覆蓋到所有的渲染請(qǐng)況,也就是如果你的組件根據(jù)props傳入的參數(shù)渲染結(jié)果可能不同,這樣的情況必須寫(xiě)多個(gè)測(cè)試案例都覆蓋到。
-
DOM交互測(cè)試用Jest+Enzyme
enzyme有3種渲染方式:render、mount、shallow
render、mount、shallow的區(qū)別
render采用的是第三方庫(kù)Cheerio的渲染,渲染結(jié)果是普通的html結(jié)構(gòu),對(duì)于snapshot使用render比較合適。shallow和mount對(duì)組件的渲染結(jié)果不是html的dom樹(shù),而是react樹(shù),如果你chrome裝了react devtool插件,他的渲染結(jié)果就是react devtool tab下查看的組件結(jié)構(gòu),而render函數(shù)的結(jié)果是element tab下查看的結(jié)果。
這些只是渲染結(jié)果上的差別,更大的差別是shallow和mount的結(jié)果是個(gè)被封裝的ReactWrapper,可以進(jìn)行多種操作,譬如find()、parents()、children()等選擇器進(jìn)行元素查找;state()、props()進(jìn)行數(shù)據(jù)查找,setState()、setprops()操作數(shù)據(jù);simulate()模擬事件觸發(fā)。
shallow只渲染當(dāng)前組件,只能能對(duì)當(dāng)前組件做斷言;mount會(huì)渲染當(dāng)前組件以及所有子組件,對(duì)所有子組件也可以做上述操作。一般交互測(cè)試都會(huì)關(guān)心到子組件,我使用的都是mount。但是mount耗時(shí)更長(zhǎng),內(nèi)存啥的也都占用的更多,如果沒(méi)必要操作和斷言子組件,可以使用shallow。
交互測(cè)試
主要利用simulate()接口模擬事件,實(shí)際上simulate是通過(guò)觸發(fā)事件綁定函數(shù),來(lái)模擬事件的觸發(fā)。觸發(fā)事件后,去判斷props上特定函數(shù)是否被調(diào)用,傳參是否正確;組件狀態(tài)是否發(fā)生預(yù)料之中的修改;某個(gè)dom節(jié)點(diǎn)是否存在是否符合期望。mock請(qǐng)求
需要mock掉真正的http請(qǐng)求,模擬返回值。不用擔(dān)心不準(zhǔn)確,你只用保證請(qǐng)求時(shí)的參數(shù)符合期望就好,mock的返回值按預(yù)期編寫(xiě)就好,置于這些請(qǐng)求是否真的能返回這些結(jié)果,是接口測(cè)試改干的活。
運(yùn)行并調(diào)試
在運(yùn)行測(cè)試腳本過(guò)程,Jest 的錯(cuò)誤提示信息友好,通過(guò)錯(cuò)誤信息一般都能找到問(wèn)題的所在。 同時(shí) Jest 還提供了生成測(cè)試覆蓋率報(bào)告的命令,只需要在package.json 里配置{ "scripts": { "test": "jest --coverage " }
即可生成。會(huì)在終端中顯示如下報(bào)告:
而且還會(huì)在項(xiàng)目中生成 coverage 文件夾,非常方便。
匹配器使用
推薦閱讀:
前端測(cè)試框架Jest系列教程 -- Matchers(匹配器)
Javascript單元測(cè)試工具-Jest 學(xué)習(xí)筆記(一)
測(cè)試異步代碼
推薦閱讀:
Javascript單元測(cè)試工具-Jest 學(xué)習(xí)筆記(一)
學(xué)習(xí)Jest——語(yǔ)法篇
遇到的問(wèn)題
Image.onload不能被監(jiān)聽(tīng)到
解決辦法參考:https://zhuanlan.zhihu.com/p/37329102
我采用了自己 mock Image 構(gòu)造函數(shù)方案
最后,在寫(xiě)測(cè)試用例過(guò)程中,不知道用什么匹配器,可以來(lái)Jest官網(wǎng)搜羅一圈https://jestjs.io/docs/zh-Hans/expect
不知道使用Enzyme什么API時(shí),也來(lái)Enzyme搜羅一圈http://airbnb.io/enzyme/docs/api/
總能找到你想要的~