Vue 應用單元測試的策略與實踐 01 - 前言
本文主要嘗試解決三個問題:
- 在 TDD 做完Tasking列完例項化資料之後,完全沒有UT基礎不知道該怎麼寫單元測試?
- 在Vue應用的單元測試中,對UI元件和vuex store等測試的區別有何不同?顆粒度該細到什麼程度?
- 測試收益如何最大化,如何配置高性價比的測試策略,即什麼地方到底該花力氣測試,什麼地方又可以暫且放一放?
不談論的包括:
- ATT 驗收測試 或 E2E 端到端測試,這個是我想進一步探索的話題,特別是在TDD的語境下。 ofollow,noindex">#322
- 為什麼要 TDD?但是我會講為什麼要 UT 單元測試。測試和TDD是兩碼事,而光是自動化測試的好處就已經足夠多,但是如何做到更好的自動化和持續整合,那就需要TDD來指引方向。
- Snapshot Testing 快照測試,其實我是很認可快照這種形式,但需要改進其工作流,至少結合Image Snapshot和Storybook等工具,甚至更應該放到CI上去。 #311
下面我就來結合具體場景,進一步例項化這些問題,舉幾個:chestnut::
- 在 TDD 做完Tasking列完例項化資料之後,完全沒有UT基礎不知道該怎麼寫單元測試?
// Given 一個完全沒有UT基礎的新人:walking: // When 當他:walking:閱讀和練習本文的Jest的部分 // Then 他能夠把Given/When/Then的套路學會 他能夠學會Jest的基本用法,包括測試suite和斷言等語法 他能夠學會Jest中測試非同步的幾種方式 複製程式碼
- 在Vue應用的單元測試中,對UI元件和vuex store等測試的區別有何不同?顆粒度該細到什麼程度?
// Given 一個有基本的UT知識但沒寫過Vue測試的新人:walking: // When 當他:walking:閱讀和練習本文的Vue單元測試的部分 // Then 當然,他能夠學會Vue元件在測試當中的幾種渲染方式 他能夠學會UI元件的分類,特別是互動行為的測試方式 他能夠對Vuex概念的理解更加深入,且知道 `Redux-like` 架構的好處 他能夠合理測試vuex store的mutation和getter中的業務邏輯 他能夠測試元件如何正確dispatch action以及action中如何做非同步操作 複製程式碼
- Vue專案中測試收益如何最大化,如何配置高性價比的測試策略,即什麼地方到底該花力氣測試,什麼地方又可以暫且放一放?
// Given 一個具備UT基礎但找不到著力點的求索之徒:monkey: // When 當他:walking:閱讀本文的Vue應用測試策略部分 // Then 他能夠找到測試的重點,重新燃起對UT的熱情:fire: 他能夠在專案背景下合理配置單元測試的測試策略 複製程式碼
於是乎,這就是本系列文章的大綱,先放出來給大家一個對於Vue應用單元測試的全域性觀:
## 單元測試基礎 ### 為什麼選擇 Jest ### Jest 的基本用法 ### 該如何測試非同步程式碼? ### 單元測試與自動化的意義 ## Vue 單元測試 ### Vue 元件的渲染方式 ### Wrapper `find()` 方法與選擇器 ### UI 元件互動行為的測試 ## Vuex 單元測試 ### CQRS 與 `Redux-like` 架構 ### 如何對 Vuex 進行單元測試 ### Vue元件和Vuex store的互動 ## Vue應用測試策略 ### 單元測試的特點及其位置 ### 單元測試的關注點 ### 應用測試的測試策略 複製程式碼
:hushed: 哦豁,正文終於開始……
單元測試基礎
引用 好友 鮮明的觀點就是: 寫不好是能力問題,不寫則是態度問題 。單元測試客觀上可以讓開發者的工作更高效,Vue 應用的單元測試是一定要的。
單元測試的上下文
談任何東西都一定要有個上下文。你的論述不能是「因為單元測試有這些好處,所以我們要做單元測試」,而應該是「不做單元測試我們會遇到什麼問題」,這樣才能回答「為什麼要寫單元測試」的問題。那麼我們談論單元測試的上下文是什麼呢?不做單元測試我們會遇到什麼問題呢?

上圖為一個產品從 idea 分析、設計、開發、測試到交付並獲取市場反饋的過程。
而 單元測試的上下文就是存在於「敏捷」當中 。敏捷為的是更快地交付有價值的可工作的軟體。為此,它有一個指標來度量這個「更快」,那就是 lead time,它度量的是一個 idea 從提出被驗證,到最終上生產環境面對使用者的時間。顯然,這個時間越短,軟體獲得反饋的時間就越短,對價值的驗證就越快發生。
單元測試的意義
這個結論對我們寫不寫單元測試有什麼影響呢?答案是,不寫單元測試,你就快不起來。為啥呢?因為每次釋出,你都要投入人力來進行手工測試;因為沒有測試,你傾向於不敢隨意重構,這又導致程式碼逐漸腐化,複雜度使得你的開發速度降低。
那麼在這個上下文中來談要不要單元測試,我們就可以很有根據了,而不是“開發爽了就用,不爽就不用”這樣含糊的答案:
if-else
除此之外,你就需要寫單元測試。如果你想隨時整理重構程式碼,那麼你需要寫單元測試;如果你想有自動化的測試套件來幫你快速驗證提交的完整性,那麼你需要寫單元測試。
單元測試與自動化的關係
綜上,我們用來談論單元測試的「透鏡」是什麼呢?一言以蔽之,兩點: 反饋速度 和 自動化 。
自動化回答的是 要不要自動化的單元測試 這個問題。測試是重構的唯一保障,也就是說,沒有測試,基本上就沒法重構程式碼(重構指的是 不改變軟體可觀測行為的前提下改善程式碼內部設計或實現 ),基本上就只能看著程式碼腐化。那麼,基本上只要你的系統需要持續發展,你就需要單元測試。
反饋速度回答的是 要不要 TDD、測試先行還是後補 這個問題。答案是,需要 TDD,最好先行,因為 可以提高反饋速度 ,縮短反饋週期,與此同時減少不必要的浪費。
至此,回答了「為什麼我們需要寫單元測試」的問題。下面讓我們來談談如何寫好 JavaScript 程式碼和 Vue 應用框架的單元測試。
為什麼選擇 Jest

引自技術雷達:Jest是一個“零配置”的前端測試工具,具有諸如模擬和程式碼覆蓋之類的開箱即用特性,主要用於React和其他JavaScript框架。
我們團隊對採用JEST做前端測試的結果非常滿意。它提供了一種“零配置”的開發體驗,並具備諸多開箱即用的功能,比如 Mock 和程式碼覆蓋率等。你不僅可以將此測試框架應用於React.js應用程式,也可以應用於其他 JavaScript 框架。Jest 經常被炒作的功能之一是使用者介面的快照測試。快照測試可以作為測試金字塔上層一個很好的補充,但請記住,單元測試仍然是堅實的基礎。
Jest 的幾大好處可以涵蓋為:
- Fast 天下武功,唯快不破。確實很快,雖然實測下來跟 Mocha 4 還是慢了些,以後找個機會再測一次。
- Opinionated 不需要你做出選擇和配置,就能提供所有的東西,比如Mock(幹掉Sinon)、Test Runner(幹掉Karma)、Matcher(幹掉Chai)、Test Coverage(內建istanbul)
- Watch Mode 注重開發者體驗,能夠在編碼的時候幫助我們快速獲得測試結果的反饋。
- Snapshot Testing 這一點是值得爭議的一點,前文也提到過會專門開個issue來討論,在此不再贅述。
總結一下
Jest 最大的特點是它是一個非常有效的解決方案,不需要與其他測試庫互動來執行它的工作。與此同時 Jest 非常注重開發者體驗,這一點也是特別值得欣賞,現在市面上關注開發者(“人”)體驗的開發框架和工具實在不多,而Jest Watch模式的核心就在於快速獲得反饋,雖然我沒在命令列使用而是WebStorm但亦可以與之結合。
ps: 除此之外,還有很多開發者體驗亦值得細細品味與發現,特別是Jest本身來自Facebook的工程化支援也是特別棒的,這個講述如何開發Jest的官方視訊值得一看: Building High-Quality JavaScript Tools 。