Jest | 測試設置分類(describe)及作用域(scoping)

神Q超人
Enjoy life enjoy coding
6 min readFeb 15, 2019
使用 describe 替 test 做分類

前言

關於 describe ,在進行測試時其實是很基本的分類,但是因為 describe 牽扯到了作用域,而在作用域內的 beforeAllafterAllFunction 又和 async 異步測試有關,所以本篇文章的內容可能會需要先了解「Unit Test | 跨越同步執行的 Jest 測試」裡所提到的幾個用法,如果有任何問題再麻煩留言告訴我,謝謝!

describe

在講解之前,可以先看一些基本的測試:

上方對 sum 做了三次測試, square 做了一次,通過測試後得到了 PASS 的結果:

所有測試內容混在一起,不容易看出是在測試什麼 Function

所有的測試內容都會條列顯示,雖然可以清楚的知道在每一項測試中做了什麼事情,但卻無法曉得該測試是對哪個 Function 做的,而就一般來說,測試檔案裡也不會只需測試一個 Function 而已。

因此,需要把測試用 describe 分類,讓測試者可以一眼就能知道哪些測試內容是對哪個 Function 使用。

describe 的使用方法很簡單,就像 test 一樣,它會接收兩個參數,第一個是對 describe 的描述,第二個是 Function ,屬於此 describetest 都放在該 Function 中。

將上方的例子做分類會得到:

經過分類後再進行測試,會更清楚每一項測試是在哪個 Function 身上:

經過分類後會更清楚每一項測試是在哪個 Function 身上

scoping

每個 .test.js 測試檔案的內容就如一般的 JavaScript ,依照 Function 的範圍分成全域及區域的執行。

在測試中,執行範圍會影響到的除了變數外還有另外幾個 Jest 提供的函式:

  1. beforeAll :所在區域內會第一個執行。
  2. beforeEach :每一次的測試前會先執行。
  3. afterAll :所在區域內最後一個執行。
  4. afterEach :每一次的測試後會馬上執行。

可由以下例子更清楚它們的執行順序:

執行結果:

beforeAll , afterAll , beforeEach , afterEach 在全域及區域內的執行順序

beforeAllafterAll 一定是全域和區域內的第一個執行,而 beforeEachafterEach 則會夾住 test ,分別會在單一測試的前後執行,只要記住全域的 before 一定是最先, after 是最後。

在測試裡,可以利用 beforeAllbeforeEach 初建立測試資料,並在測試完後以 afterAllafterEach 將資料給移除。

接著透過實際運用來理解這四個函式的使用方法:

上方例子使用 userDB 模擬資料庫的資料,並在測試前透過 beforeAll 新增一筆測試資料,測試完後再以 afterAll 將測試資料清除,最後利用全域 afterAll 最後執行的特性確認 userDB 是否回到初始狀態:

測試成功,且最後全域的 afterAll 執行時, userDB 已無測試資料

既然是模擬資料庫,一定會有一些延遲時間,所以替 insertTestData 增加 setTimeout

//在新增測試資料增加 Timeout
const insertTestData = data=> {
setTimeout(() => {
userDB.push(data)
},3000)
}

其餘不變的狀況下再進行測試一次:

Received 的值是 undefined ,不符合期望

因為 Timeout 延遲的關係,對 getUserData 執行測試的時候,測試資料還沒有被 pushuserDB 裡面,因此在找不到資料的情況下函式就回傳 undefined ,這個結果並不是測試所期望的。

beforeAll 等函數中,處理異步執行有幾種方法:

第一種是當 insertTestData 中含有 callBack 函式時,可以使用 done 來設置 beforeAll 的完成點,只要沒有執行到 done 就不會離開 beforeAll ,例如將 insertTestDatabeforeAll 改成下方:

這麼一來,就能確保是在新增資料後才會接著測試,結果就會正確。

第二個方式是,在 insertTestData 本身就回傳一個 Promise 物件的情況,只需要在 beforeAll 中回傳從 insertTestData得到的 Promise 就可以了:

上方的兩種方式都能為 beforeAll 等函式處理同步執行產生的問題,得到結果也相同,測試過程當然就不會出錯!

關於處理同步執行更詳細說明可以參考「Unit Test | 跨越同步執行的 Jest 測試」,裡面會有更清楚的例子。

本篇文章主要是在整理測試的程式內容,能夠使用 describe 為相同函式的測試內容做分類,並使用 beforeAllafterAllbeforeEachafterEach 等函式建構及清除測試環境。

如果文章中有任何問題,或是不理解的地方,都可以留言告訴我!謝謝大家!

參考文章

  1. https://jestjs.io/docs/en/setup-teardown

--

--