前戲
最近寫了一個 wechat-colorpicker 小專案。 主要是為了練習下TS。既然寫了一個小庫,我就想著順便學下如何寫測試吧,這是一件蠻有意思的事情。
從選型到搭建環境,前前後後用了近2個小時。不得不說一個合格的前端必然是一個合格的配置工程師。再次列舉下,這個專案中所需要搭建配置的工具。
- webpack.config 自動編譯ts+css
- tsconfig.config ts的配置檔案
- tslint.json tslint的配置檔案
- jest.config 配置jest
- .babelrc jest解析js時還會需要用到的外掛
- circle.yml CircleCI 配置檔案
如果大家有什麼不懂的,自行百度
Jest + TS 入門
第一個問題,我專案都是TS寫的,自然會有 import 這樣的語法怎麼辦?
通過官網的Getting started 我們可以在最下方找到 ts-jest 不難理解,我們需要配的其實就是jest載入到什麼樣型別的檔案,使用什麼預處理來處理檔案。
transform: {
'.*\\.(ts)$': '<rootDir>/node_modules/ts-jest/preprocessor.js',
},
複製程式碼
transform 就是專門用來匹配各種檔案字尾,然後進行對應的預處理,你可以理解為webpack裡的loader
我在TS中引入了.css檔案咋辦?同上
既然有transform,那我們任何檔案都可以通過transform進行預處理了。
transform: {
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
'.*\\.(ts)$': '<rootDir>/node_modules/ts-jest/preprocessor.js',
'^.+\\.(css)$':"<rootDir>/node_modules/jest-css-modules"
},
複製程式碼
如果是js檔案我通過babel-jest處理,css則使用jest-css-modules。假如沒有這些配置,那import了你的庫,庫裡有引入了高特性的js檔案,或者css檔案就會編譯報錯。
關於rootDir
在進行技術選型的過程中,我看了最新版本的vue-cli裡推薦用哪些框架進行測試,一個是jest,還一個是krama+mocha。 我選擇了jest,jest本身是fb出的,對於react非常友好。本身也做了許多環境上的封裝切換jsdom環境或者node環境非常方便。我最後選擇了這個。
剛剛開始看vue-cli裡的jest配置我是拒絕的,第一個最顯眼的關鍵字就是<rootDir>
這種像XML得東西。但是你慢慢靜下心來去理解就很容易了,其實就是一個basePath的感覺。我們可以看下文件怎麼說 rootDir
我的目錄如下
--- __test__
jest.config.js
--- dist
--- node_modules
--- src
複製程式碼
//jest.config.js
module.exports = {
rootDir: path.resolve(__dirname, '../'),
}
複製程式碼
<rootDir>
其實就代表根目錄了
setupFiles 選項
setupFiles是一個AOP的配置,我覺得這個非常好用!因為jest是通過jsdom是模擬了一個document的執行環境,那必然還有很多可能是沒有的,比如localStorage,那我們可以通過該配置來設定我們啟動前,需要載入什麼,比如vue-cli中就是設定了Vue.config.productionTip = false,而我們可以讓環境支援localStorage。
setupFiles: ["jest-localstorage-mock"]
複製程式碼
不難發現,其實jest的生態還是很豐富的,我本次遇到的問題谷歌幾個關鍵字很快都能解決
UI Test 該怎麼寫?
test應該是像純函式一樣保證輸入輸出都是一樣的,UI test一方面與Dom耦合,另一方面又使用者互動耦合,那具體應該怎麼寫呢?
思路是:模擬使用者操作,再通過Dom進行判斷是否渲染正確。
比如這個例項化的測試,我們可以測試是否初始化是否正常,通過jquery來輔助判斷
// 例項化測試
import WeChatColorPicker from '../src';
import $ from 'jquery';
export function newInstance() {
document.body.innerHTML = `<div id="container"></div>`;
return new WeChatColorPicker(pickerOptions);
}
const baseColorArr = [ ... ];
test('test new instance', () => {
const instance = newInstance();
expect(instance.baseComponent.baseColorArr).toEqual(baseColorArr);
expect($('.wechat-colorpicker')).not.toBeNull();
});
複製程式碼
比如這個是點選【基本色】【更多顏色】我們會切換class,那就可以像這樣
// tab class切換的互動測試
import $ from 'jquery';
import { newInstance } from './utils';
describe('change tab test', () => {
newInstance();
test('use base color', () => {
$('.wechat-picker-box p i').eq(0).click();
expect($('.wechat-colorpicker').hasClass('base-color')).toBe(true);
});
test('use picker', () => {
$('.wechat-picker-box p i').eq(1).click();
expect($('.wechat-colorpicker').hasClass('more-color')).toBe(true);
});
});
複製程式碼
是不是突然就覺得非常簡單了?並且是唯一性的,測試用例可靠性也有保障。 之後我們就只需要配合一個CI,每次提交前跑一邊我們的測試程式碼,所有用例測試成功即可pr,否則直接被拒絕。
寫完了測試,給我們的jest.config 多加一行配置,來生成我們的測試報告(Jest內建了istanbul)
module.exports = {
// ...
collectCoverage: true,
// ...
}
複製程式碼
接著執行下 npm t
檢視測試結果如下
- % Stmts 是語句覆蓋率(statement coverage):是否每個語句都執行了?
- % Branch 分支覆蓋率(branch coverage):是否每個if程式碼塊都執行了?
- % Funcs 函式覆蓋率(function coverage):是否每個函式都呼叫了?
- % Lines 行覆蓋率(line coverage):是否每一行都執行了?
更多測試用例前往 >>> repo-wechat-colorpicker <<< 檢視
CricleCI(番外篇)
我們可以通過CI的工具來完善我們的wordflow,在這我選用了CricleCi。進入官網我們直接github登入後,setup 我們的專案。
然後根據它的推薦走,在我們專案根目錄新增一個cricle.yml,複製黏貼它的推薦配置即可。
然後我們push測試一下,在這裡我寫錯了我的檔案路徑,所以構建報錯了。
重新修復了問題後,就可以正常執行工作了。
由於本文不是重點介紹CI,這裡就不過多展開了,有興趣的朋友可以自己摸索下
後面真的沒有了
至此,你應該對前端UI測試應該大致有一個巨集觀的瞭解。
本文沒有過多得介紹Jest的用法或者語法,希望可以給不知道如何做測試的朋友們一點方向,自己去嘗試找到適合自己專案的才是最好的。
剛剛開始可能很難,無從下手,成本很大。實際上做起來,其實都是慢慢的套路,寫熟練了後應該會上癮,畢竟最後跑完測試的那感覺會讓你達到高潮。