Jest | 讓 Jest 為你的 Code 做測試-基礎用法教學
前言
單元測試是進入前端工程後一直很想學的技能,主要是做過測試能讓自己的程式碼維持一定的水準,尤其在團隊開發時,更不會在上線時因為沒注意到某個細節而產生 Bug ,導致專案出現問題。
單元測試
單元測試是指為專案中每個單一行為做測試,通常專案裡的最小單位都是一個 function
,當每個 function
經過測試,確保邏輯是正確的,那當他在專案裡運行時也就比較不會發生問題,且留下的測試文件也可以在團隊討論或交接時更清楚。
Jest
用於前端的測試框架不是只有 Jest
,選擇原因是因為筆者較擅長使用 React
,而 Jest
在測試方面和 React
的整合度較佳。除了 Jest
以外,常聽到的測試框架還有 mocha
。
建立專案
首先到專案資料夾的目錄下,在 node.js
環境下創建 npm
專案:
npm init -y
這時候在專案資料夾內會產生記錄著專案開發設定的 package.json
,如果還不曉得如何安裝 node.js
可以參考「第一次建置node.js開發環境和安裝npm就上手!」的說明。
下載套件
透過 npm
套件管理工具下載 Jest
測試框架到專案的執行環境中:
npm install jest --save-dev
設定測試指令
打開 package.json
,可以看到剛剛下載的 Jest
已經被記錄在 devDependencies
中了:
在上圖第一行的 scripts
是在 npm
的開發環境中設定執行指令的地方,上方的 test
便是預設的指令之一,可以直接把他的內容改掉,如下:
scripts: {
"test": "jest"
}
設定好後,只需在終端機中使用以下方式輸入,便能執行設定好的對應指令:
npm run test //對應指令
需要注意的是,如果是使用 npm
的 scripts
執行指令,那他的執行環境就是專案本身,尋找執行環境中的 Jest
或其他套件執行。
換個說法,直接在終端機中輸入 jest
,執行環境就不會在專案內,而是以全域為主,但是全域環境下並沒有安裝 Jest
便會出錯,除非將 Jest
安裝在全域中:
npm install jest -g // -g 代表全域
建立測試
Jest
在執行測試時,會尋找專案中副檔名為 .test.js
結尾的檔案,但不限制要放在哪個資料夾,所以在根目錄新增一個 index.test.js
建立第一個測試:
把上方的 test
當作一個函式,負責描寫一個單元測試,他擁有兩個參數:
- 第一個參數為「測試名稱」,能夠簡單描述這部分是在測試什麼邏輯或功能。
- 第二個參數是一個函式,又稱斷言,函式內的
expect
用來描述被測試的內容,toBe
是測試內容的回傳值是否符合期望值,例如上方的測試內容為「5加上2期望會等於7」。
執行測試
在終端機中輸入在 scripts
中設定好的指令:
npm run test
執行後會顯示測試的結果:
結果內會顯示 Jest
測試了哪些 .test.js
檔案,還有每個測試( expect
)內的結果( toBe
)是否正確符合,符合的話會輸出 PASS。
現在把 toBe
內的數字改成 8 ,再進行一次測試:
當測試失敗時, Jest
會再結果中顯示哪個檔案內的測試有問題,並會提示正確的結果 Received
。
這就是使用 Jest
測試的基本方法,但實際上需要測試的函式都已經寫好了,並不會在 expect
中寫下邏輯,因此可以直接在 expect
中呼叫函式,測試結果的正確性,例如:
其他斷言
斷言的種類有很多,上方的 toBe
只是其中一種測試方式,除此之外還有以下的斷言可以使用:
除了 toBe
外,對字串還可以用 toMatch
搭配正規表達式檢查:
確認物件是否等於期望值需使用 toEqual
:
預防函式回傳某個結果可以使用 not
:
上方的第 9 行 peopleA.name
是空的,而在使用 not
的情況下結果需不等於期望值,所以不會通過測試:
確認數字結果的斷言:
需要注意在 JavaScript
中的小數點運算會產生誤差,因此浮點數需要使用 toBeCloseTo
做斷言,他會捨棄掉些微的誤差:
上方使用 toBe
會不通過測試,因為 toBe
需要完全符合:
對陣列可以用 toContain
判斷陣列內是否含有某值,或搭配迴圈對每個位置做斷言:
最後是用來判斷特殊值的斷言,例如 undefined
、 null
、 true
等等:
產生覆蓋率報告
在測試的時候,會使用各種斷言來確認結果是否與期望值符合,但是如果測試的內容遺漏了某個條件分支,便無法確認該分支的邏輯性是否正確。
覆蓋率就是用來統計被測試的函式,程式碼的執行比例,當函式內所有程式都被測試過,那覆蓋率就會呈現 100% 。
另外, Jest
內建的覆蓋率會以每個 JavaScript
檔案統計,因此在產生前還需要將「函式」與「測試」檔案分開,如下:
建立 ./funcs/func.js
放要測試的函式:
func.js
中的 sum
有兩個分支,一個是在 b
有值的時候回傳 a + b
,另一個是在 b
沒有值的情況下直接回傳 a
,最後使用 module.exports
將 sum
匯出。
接著建立測試檔案 ./__test__/index.test.js
:
最後到 package.json
中在 test
的指令後加上 --coverage
,讓 Jest
執行完時同步產生測試報告,當然也可以另外設定新指令:
執行測試後,除了測試結果外,還會產生覆蓋率統計資訊:
也可以發現在專案目錄下多了一個叫做 converage
的資料夾,裡面的 Icov-report
內有個 index.html
,打開後也可以看到相同的資訊:
透過點擊 func.js
可以確認更詳細的測試過程,包含是哪一行沒有執行,或每行各執行了幾次:
現在為 ./funcs/func.js
內的 sum
增加一個斷言句,讓 Jest
在測試時進入 sum
的另一個分支:
執行測試後再一次點開 converage
內的 html
測試報告:
func.js
的詳細執行資訊,在判斷 b
是否有值的地方執行了兩次,且已經沒有還未覆蓋的區塊:
本文解釋了基本的 Jest
測試,並簡單描述斷言庫和產生覆蓋率報告,今後的文章會繼續解釋 Jest
提供的其他功能,一直到用於測試 React
的 Component
組件。
如果文章中有任何問題,或是不理解的地方,都歡迎留言告訴我,謝謝大家!
參考文章