我們團隊中的專案眾多,基本上都沒有配置單元測試,其中一個 vue2.0 專案是我們的主站專案,很早之前我就想給這個專案加上單測,只是一直忙於業務就沒顧上。正巧馬上過年了,最近需求不多,忙完需求,就開始搞搞單測。
從有配置單測的想法我就一直在思考,我們這個專案是否真的需要加單測,我們要測試什麼,那麼多的測試執行器又該怎麼選擇,以及怎麼在團隊中推行單測。基於這些思考,開始實施了。
我們是否真的需要單元測試
目前整個團隊的所有的專案都沒單測,而其它團隊的專案很多都有對應的測試工具,總覺得我們技術棧少了點什麼。這雖然是我要加單測的充分條件,卻是我想配置單測的初衷。
專案背景
其次我們這個專案維持了四五年,進行了至少4次專案架構重構的升級,這個專案中有主要有 v7 版、v8 版,總計 近200 個頁面,目前大部分的業務都在 v8 版。當然我們還有 v9 版,由於專案業務不斷增多,不得不對倉庫進行拆分,v9版 是基於 vue-cli 搭建的的一個新倉庫,這裡就不在贅述了。前兩版的技術棧選型分別是:
- v7版
juicer + jQuery
- v8版
vue2.0 + webpack
就現狀來看,給v8版配置單測比較合適,一方面主要業務在v8上,另一方面從使用的 vue2.0 + webpack
技術棧來看,更適合寫單元測試。
預期期望
我期望給 v8 版的公共元件和工具方法都加上單元測試,這對團隊程式碼的可靠性驗證來說肯定是有益的。後期迭代,也可以通過單測防止意外情況的發生。嗯,這就是要加單測的必要條件吧。
除此之外,元件的單元測試還可以為我們帶來更多的好處:
- 提供描述元件行為的文件
- 節省手動測試的時間
- 減少研發新特性時產生的 bug
- 改進設計
- 促進重構
自動化測試可以幫助團隊中的開發者可以維護複雜的基礎程式碼。單元測試是測試體系中最有用的,即能幫助開發者思考如何設計一個元件,又可以幫助開發者重構一個現有元件。
一開始,當大家對一個專案的新增單測的願景還不夠清晰的時候,單元測試可能會拖慢開發進度,但是一旦大家的願景建立起來並且有真實的使用者對這個應用產生興趣,那麼單元測試就是絕對有必要的了,它們會確保基礎程式碼的可維護性和可擴充套件性。
如何選擇測試執行器
單元測試應該具備:
- 可以快速執行
- 易於理解
- 只測試一個獨立單元的工作
Vue Test Utils 是 Vue 元件單元測試的官方庫,官方推薦兩個測試執行期:
Jest
是功能最全的測試執行器。它所需的配置是最少的,預設安裝了JSDOM
,內建斷言且命令列的使用者體驗非常好。不過你需要一個能夠將單檔案元件匯入到測試中的前處理器。我們已經建立了vue-jest
前處理器來處理最常見的單檔案元件特性,但仍不是vue-loader
100% 的功能。mocha-webpack
是一個webpack + Mocha
的包裹器,同時包含了更順暢的介面和偵聽模式。這些設定的好處在於我們能夠通過 webpack +vue-loader
得到完整的單檔案元件支援,但這本身是需要 很多配置 的。
我個人更偏向於 mocha-webpack
,畢竟測試單檔案元件,上手又快、功能又全。
配置 mocha 單元測試
瀏覽器環境
Vue Test Utils 依賴瀏覽器環境,用 JSDOM
在 Node
虛擬瀏覽器環境執行測試。
Vue
的單檔案元件在它們執行於 Node
或瀏覽器之前是需要預編譯的。我們直接使用 webpack
。針對 mocha
需要基於 webpack
+ vue-loader
進行設定。
選擇了 mocha-webpack
測試單檔案元件,是通過 webpack 編譯所有的測試檔案然後在測試執行器中執行。這樣做的好處是可以完全支援所有 webpack 和 vue-loader
的功能。mocha-webpack
能夠提供了非常流暢的體驗。
1. 設定 mocha-webpack
v8專案基於已經安裝並配置好了 webpack
、vue-loader
和 Babel
。首先要做的是安裝測試依賴:
npm install --save-dev @vue/test-utils mocha mocha-webpack
複製程式碼
在 package.json
中定義一個測試指令碼。
// package.json
{
"scripts": {
"test": "mocha-webpack --webpack-config webpack.config.js --require test/setup.js test/**/*.spec.js"
}
}
複製程式碼
2. 暴露 NPM 依賴
將依賴外接以提升測試的啟動速度,通過 webpack-node-externals
外接所有的 NPM
依賴:
// webpack.config.js
const nodeExternals = require('webpack-node-externals')
module.exports = {
// ...
externals: [nodeExternals()]
}
複製程式碼
3. 原始碼錶
原始碼錶在 mocha-webpack
中需要通過內聯的方式獲取。推薦配置為:
module.exports = {
// ...
devtool: 'inline-cheap-module-source-map'
}
複製程式碼
4. 設定瀏覽器環境
Vue Test Utils
需要在瀏覽器環境中執行。我們可以在 Node
中使用 jsdom-global
進行模擬:
npm install --save-dev jsdom jsdom-global
複製程式碼
然後在 test/setup.js
中寫入:
npm install --save-dev jsdom jsdom-global
複製程式碼
這行程式碼會在 Node 中新增一個瀏覽器環境,這樣 Vue Test Utils 就可以正確執行了。
5. 選用 expect
斷言庫
推薦 Jasmine/Jest 風格的 expect
斷言
npm install --save-dev expect
複製程式碼
然後在 test/setup.js
中編寫:
require('jsdom-global')()
global.expect = require('expect')
複製程式碼
6. 為測試優化 Babel
mocha
是比較常用的 node
測試框架,但是隻支援 commonjs
模組,要讓 mocha
支援 ES6
模組,需要 babel
的幫助。babel-loader
將會自動使用相同的.babelrc配置檔案。
寫單測的注意事項
- describe 測試套件
- 每個 it 塊只做一個斷言,it塊稱為"測試用例"
- 讓測試描述更簡短清晰
- 只提供測試需要的最小化資料
- 把重複的邏輯重構到了一個工廠函式中
小結:
目前已經寫了一些單測,預期是給公共元件和工具類函式都加單測。業務需求示情況新增單測。
Vue 元件單元測試的一般思路:渲染這個元件,然後斷言這些標籤是否匹配元件的狀態。
通常,在實現完成後新增測試時,開發們傾向於接受程式生成的輸出,而不必通過手動計算仔細檢查結果。 將要求轉化為可偽造的測試。
疑問
好像已經形成了習慣,每次都會留下一些疑問,後面慢慢解疑吧。
- 如何在元件中測試 Vue-router
- 如何在元件中測試 Vuex
- 如何提升測試的啟動速度?
- chai斷言庫與 Jest的 expect 有什麼區別
- Sinon 是什麼
- mixin、watch、computed如何新增單測