Jest | 測試設置分類(describe)及作用域(scoping)
前言
關於 describe
,在進行測試時其實是很基本的分類,但是因為 describe
牽扯到了作用域,而在作用域內的 beforeAll
和 afterAll
等 Function
又和 async
異步測試有關,所以本篇文章的內容可能會需要先了解「Unit Test | 跨越同步執行的 Jest 測試」裡所提到的幾個用法,如果有任何問題再麻煩留言告訴我,謝謝!
describe
在講解之前,可以先看一些基本的測試:
上方對 sum
做了三次測試, square
做了一次,通過測試後得到了 PASS
的結果:
所有的測試內容都會條列顯示,雖然可以清楚的知道在每一項測試中做了什麼事情,但卻無法曉得該測試是對哪個 Function
做的,而就一般來說,測試檔案裡也不會只需測試一個 Function
而已。
因此,需要把測試用 describe
分類,讓測試者可以一眼就能知道哪些測試內容是對哪個 Function
使用。
describe
的使用方法很簡單,就像 test
一樣,它會接收兩個參數,第一個是對 describe
的描述,第二個是 Function
,屬於此 describe
的 test
都放在該 Function
中。
將上方的例子做分類會得到:
經過分類後再進行測試,會更清楚每一項測試是在哪個 Function
身上:
scoping
每個 .test.js
測試檔案的內容就如一般的 JavaScript
,依照 Function
的範圍分成全域及區域的執行。
在測試中,執行範圍會影響到的除了變數外還有另外幾個 Jest
提供的函式:
beforeAll
:所在區域內會第一個執行。beforeEach
:每一次的測試前會先執行。afterAll
:所在區域內最後一個執行。afterEach
:每一次的測試後會馬上執行。
可由以下例子更清楚它們的執行順序:
執行結果:
beforeAll
和 afterAll
一定是全域和區域內的第一個執行,而 beforeEach
和 afterEach
則會夾住 test
,分別會在單一測試的前後執行,只要記住全域的 before
一定是最先, after
是最後。
在測試裡,可以利用 beforeAll
或 beforeEach
初建立測試資料,並在測試完後以 afterAll
或 afterEach
將資料給移除。
接著透過實際運用來理解這四個函式的使用方法:
上方例子使用 userDB
模擬資料庫的資料,並在測試前透過 beforeAll
新增一筆測試資料,測試完後再以 afterAll
將測試資料清除,最後利用全域 afterAll
最後執行的特性確認 userDB
是否回到初始狀態:
既然是模擬資料庫,一定會有一些延遲時間,所以替 insertTestData
增加 setTimeout
:
//在新增測試資料增加 Timeout
const insertTestData = data=> {
setTimeout(() => {
userDB.push(data)
},3000)
}
其餘不變的狀況下再進行測試一次:
因為 Timeout
延遲的關係,對 getUserData
執行測試的時候,測試資料還沒有被 push
進 userDB
裡面,因此在找不到資料的情況下函式就回傳 undefined
,這個結果並不是測試所期望的。
在 beforeAll
等函數中,處理異步執行有幾種方法:
第一種是當 insertTestData
中含有 callBack
函式時,可以使用 done
來設置 beforeAll
的完成點,只要沒有執行到 done
就不會離開 beforeAll
,例如將 insertTestData
和 beforeAll
改成下方:
這麼一來,就能確保是在新增資料後才會接著測試,結果就會正確。
第二個方式是,在 insertTestData
本身就回傳一個 Promise
物件的情況,只需要在 beforeAll
中回傳從 insertTestData
得到的 Promise
就可以了:
上方的兩種方式都能為 beforeAll
等函式處理同步執行產生的問題,得到結果也相同,測試過程當然就不會出錯!
關於處理同步執行更詳細說明可以參考「Unit Test | 跨越同步執行的 Jest 測試」,裡面會有更清楚的例子。
本篇文章主要是在整理測試的程式內容,能夠使用 describe
為相同函式的測試內容做分類,並使用 beforeAll
、 afterAll
、 beforeEach
、 afterEach
等函式建構及清除測試環境。
如果文章中有任何問題,或是不理解的地方,都可以留言告訴我!謝謝大家!
參考文章