本文取自筆者的開源項目 前端進階之路javascript
有興趣的能夠了解一下,目前還在寫做中。css
在這部分的內容中,你將學習到如下幾點:html
單元測試是用來測試程序中一小塊功能的,好比說一個函數、一個類。它能很顯著地提升項目的代碼質量,下降出現 Bug 的頻率,而且也利於維護代碼。前端
可是實際狀況是絕大部分開發者是不肯意作這件事情的。由於平時開發都忙不過來,哪還有時間去作這些事情。vue
我我的其實認爲業務代碼的測試應該是不強求的,畢竟需求常常在變化。若是對業務代碼進行高覆蓋率的測試,那麼一旦需求變更就須要同步修改測試用例。這樣編碼的壓力是雙份的,極可能達不到快節奏上線的目的。java
可是對於依賴的基礎組件庫以及公共函數是必定須要編寫單元測試的。由於這些內容會被多個模塊使用到,而且也不會頻繁變動這些基礎的功能,編寫單元測試的收益相對來講高得多。就好比各類知名的開源項目的測試覆蓋率每每是高於 90% 的,測試覆蓋率低或者壓根不寫測試的開源項目通常不多直接用於項目中。node
那麼咱們如何學習這方面的內容呢?首先不管你使用什麼技術棧,都須要先選擇一個測試框架。Jest 是其中一個相對來講優秀的框架(不少知名開源項目也都在使用它),開箱即用,內部集成了斷言庫、Mock、快照功能等等。固然你也能夠一樣選擇別的框架,核心內容都是同樣的,無非 API 有所改變罷了。react
Jest 總歸是個使用起來很簡單的框架,不須要太多的學習時間就能上手了。另外若是你想學習如何用好這個框架,最好的辦法實際上是閱讀工具庫以及組件庫的測試用例。git
如下是對 Jest 一些重要功能的簡單介紹。github
在 Jest 中使用最多的就是內部的斷言庫了,由於咱們須要用它來測試函數的輸出是否與咱們預期的一致。
它的用法也很簡單,你稍微會點英文就能看懂一段測試代碼的用途,甚至於不須要去翻閱文檔。好比說你指望一個函數的輸出爲 2
// 翻譯出來就是我測試一段代碼,指望函數(輸入)等於我指望的輸出
test('測試 1 + 1 = 2', () => {
expect(sum(1, 1)).toBe(2)
})
複製代碼
關於這部分的內容你們只須要翻閱下文檔就能熟練使用了。
異步獲取數據確定是一個常見場景了。異步代碼一般會有兩種寫法,分別爲:
在測試異步代碼的時候,一般返回的數據是不肯定的,所以咱們只須要測試異步代碼是否正常返回數據便可。
// 回調函數的寫法,經過 done 來讓測試代碼一直等待
test('fetch success', done => {
fetch(data => {
expect(data.success).toBe(true)
done()
})
})
// 函數返回 promise 的寫法,注意要加上 return
// 固然對於返回 promise 的函數咱們也能夠直接使用 await
test('fetch success', () => {
return fetch().then(data => {
expect(data.success).toBe(true)
})
})
複製代碼
假設咱們須要測試一個回調函數是否被執行、參數或者返回值是否正確,這時候咱們就可使用 Mock 函數。
function foo(cb) {
cb(1)
}
const mockCallback = jest.fn(value => value + 1)
// 回調被調用
expect(mockCallback).toBeCalled()
// 回調函數參數爲 1
expect(mockCallback.mock.calls[0][0]).toBe(1)
// 回調函數返回值爲 2
expect(mockCallback.mock.results[0].value).toBe(2)
複製代碼
固然 Mock 函數還有更多用法。好比模擬返回值,追蹤函數被調用的各類狀況等等,更多的內容能夠閱讀文檔去學習。
快照在測試組件時是個頗有用的功能,能夠幫助咱們確保在維護代碼的過程當中不會對組件的 UI 進行改變。
用法至關簡單:
expect(組件實例).toMatchSnapshot()
複製代碼
以上代碼在第一次執行時會生成快照,在接下來的測試中每次都會去對比二者的內容是否一致。
Jest 和 Babel 同樣,使用的時候都須要一個配置文件。對於 Jest 來講,你須要在根目錄中建立一個名爲 jest.config.js
的文件。
如下是一些常見的配置選項:
module.exports = {
// 文件後綴
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
// 文件如何轉換
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
'jest-transform-stub',
'^.+\\.jsx?$': 'babel-jest'
},
// 忽略的文件
transformIgnorePatterns: ['/node_modules/'],
// 生成快照須要的插件
snapshotSerializers: ['jest-serializer-vue'],
// 須要執行哪些目錄下的測試用例
testMatch: [
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
],
// 在執行用例前的配置文件
setupFiles: ['./tests/setup.js'],
// 測試覆蓋率配置
collectCoverage: true,
coverageReporters: ['html', 'lcov', 'text-summary'],
coverageDirectory: './test/coverage',
collectCoverageFrom: ['components/**/*.vue']
}
複製代碼
更多的配置屬性能夠查閱文檔學習。
對於工具函數來講,首要一點就是這個函數不能包含太多的功能,拆分紅一個個功能函數是最佳的方式,由於這樣測試起來會很方便。
另外對於工具函數來講,輸出應該是可控的,因此寫單測起來很容易,只須要 except
函數的輸出便可。
對於組件來講,最重要的是爲組件生成各個狀態下的快照,以防代碼變更後引起 UI 層面的 Bug。剩餘的內容就是對各個功能進行測試了,好比說值設置的對不對啦、事件有沒有響應啦、邏輯是否是正確啦等等,這部分的測試主要還要看具體組件的功能了。
另外若是你有作統計測試覆蓋率的話,會發現 Branch 指標的提高每每是最難的對於組件來講。一旦你能把這個指標提高到 95% 以上,那麼這個組件的問題會少不少。
推薦在完成環境配置後閱讀該文檔。
無論你是現有項目仍是新項目須要使用 Jest,均可以經過 Vue Cli 3 解決。
對於現有項目,只須要在項目文件夾中執行一條命令便可
vue add unit-jest
複製代碼
腳手架會自動在項目中幫你安裝 Jest 須要的配置,安裝完成後你會發現根目錄中新增了一個文件夾
文件夾中包含了一個測試用例,你只需執行 yarn test:unit
便可運行測試用例。
對於新項目來講,在建立項目過程當中須要選擇 Manually select features,而後按照如下內容選擇便可集成 Jest 環境。
完成環境配置之後咱們就開始進行一個簡單的組件測試吧。
PS:組件測試須要用到 @vue/test-utils
這個庫,由於須要它來幫助咱們 mount
組件以及對組件進行一系列的操做。當組件掛載之後,咱們就能夠經過 Jest 進行斷言、Mock、生成快照等等。
在 components 文件夾下咱們新增一個 loading.vue
文件
<template>
<div class="loading"> <span class="loading__indicator" :style="style" /> <span class="loading__text" v-show="text">{{ text }}</span> </div>
</template>
<script> export default { props: { text: String, size: { type: Number, default: 26 }, indicatorColor: { type: String, default: "#1989FA" } }, computed: { style() { return { width: this.size + "px", height: this.size + "px", borderColor: this.indicatorColor, borderBottomColor: "transparent" }; } } }; </script>
複製代碼
以上代碼是一個很簡單的組件,傳入 props
就完成了整個組件的渲染,沒有其餘的邏輯了。
測試用例也很簡單,完成對全部的 props
輸入輸出對比便可實現 100% 的測試覆蓋率。
describe('Loading.vue', () => {
it('renders props.msg when passed', () => {
const wrapper = mount(Loading, {
propsData: {
text: 'Loading',
indicatorColor: 'red',
size: 20
}
})
const indicatorStyle = wrapper.find('.loading__indicator').element.style
expect(wrapper.find('.loading__text').text()).toBe('Loading')
expect(indicatorStyle.borderColor).toContain('red')
expect(indicatorStyle.width).toContain('20px')
})
it('snapshot', () => {
const wrapper = mount(Loading, {
propsData: {
text: 'Loading',
indicatorColor: 'red',
size: 20
}
})
expect(wrapper).toMatchSnapshot()
})
})
複製代碼
執行 yarn test:unit
命令後,咱們應該能見到以下圖的內容
若是你想更進一步學習在 Vue 中進行單元測試的內容,推薦如下資料:
推薦在完成環境配置後閱讀該文檔。
對於新項目來講,若是你使用 create-react-app 的話,那麼默認 Jest 就集成在內部了,你只須要運行命令 yarn eject
就能夠在 package.json 文件中看到 Jest 的配置。
對於現有項目來講,你能夠經過個人 demo 或者這篇文章來學習相關的配置,這裏就再也不贅述了。
另外可能有些同窗是 TS 的環境,所以個人 Demo 中是以 TS 爲基礎配置的。
PS:組件測試須要用到 enzyme 以及 enzyme-adapter-react-16 這兩個庫,由於須要它們來幫助咱們 mount 組件以及對組件進行一系列的操做。當組件掛載之後,咱們就能夠經過 Jest 進行斷言、Mock、生成快照等等。
另外鑑於組件測試這塊的內容基本和 Vue 中的一致,所以這裏就不浪費篇幅複製代碼了,具體內容能夠去 demo 中學習。
若是你想更進一步學習在 React 中進行單元測試的內容,推薦如下資料:
總的來講在項目中進行單元測試須要學習的內容並很少,一個 Jest 外加一個可以掛載組件的庫便可,一天既能上手這塊的內容。
真正須要花時間學習的應該仍是閱讀優秀第三方庫的測試用例上。