Vitest - 介紹和建置
什麼是 Vitest ?
Vitest 是一個基於 Vite 構建的測試框架,不僅可以與 Vite 搭配使用,統一開發、測試、建構的設定,也可以獨立使用,不需要依賴 Vite。功能包括單元測試時,最常見的模擬、快照和覆蓋率報告等。
與前端另外一個常見的單元測試框架 Jest 相比,是個急起直追的後起之秀,並解決使用 Jest 遇到的幾個痛點,也高兼容了 Jest 的 API。
Vitest 啟發於在 Vite 開發測試時,現有單元測試框架中,想用來測試 Vite 都會存在一些問題,無法完美被解決,所以才有誕生 Vitest 的想法,可以參考 Vitest 團隊中 Anthony Fu 在 Fast Unit Testing With Vitest 2:45 的訪談。
Vitest v.s. Jest
1. Performance(效能)
- Vitest:支援熱模組替換(HMR)和 ESM,不需要經過 bundle,測試執行速度通常比 Jest 更快。
- Jest:模組解析較複雜,功能較多,可能在大型專案中稍慢。需要額外的轉換步驟來處理程式碼,且不支援 async 轉換和 ESM,需維護兩套設定檔。
2. Payload(負載)
- Vitest:約 26 MB / 61 個依賴套件
- Jest:約 32 MB / 196 個依賴套件
3. API
- 兩者 API 高度相似,間接降低遷移的難度。
4. Configuration(配置)
- Vitest:較為簡單,如果有使用 Vite,甚至可以共用設定文件。
- Jest:較為靈活,但相對複雜,需要單獨的設定文件。
範例:
- 使用 TypeScript,Vitest 可以開箱即用,但 Jest 需要再做轉譯的設定。
- Vitest 在開發環境下跑測試時,預設為監聽模式(watch mode),在 CI 階段自動轉換為單次運行模式(single run mode),Jest 則需要另外加參數設定。
5. ESM Support(ESM 支援)
- Vitest:原生支持 ESM。
- Jest:尚未支援,相關功能還在開發中。在瀏覽器環境下,模組需先轉換成 CommonJS 才能執行。
6. Community(社群)
- Vitest:社群相對較新,文件和教學文略少於 Jest。
- Jest:老牌測試框架,擁有大量的插件、教學文和豐富的生態系,遇到問題時更容易找到解決方案。
環境建置
安裝
npm install -D vitest
如果想直接創新的專案練習,可以改用下面的指令,或使用線上版 Vitest:
# 使用 vite 創建一個新專案
npm create vite
# 選擇完專案設定後,再安裝 vitest
npm install -D vitest
[補充]:
- 版本要求: Vite >=v5.0.0 和 Node >=v18.0.0
新增測試指令
在 package.json
,新增測試指令:
// package.json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"test": "vitest", // 新增這行
},
...
}
新增 Vitest 設定檔
在根目錄中新增 vitest.config.ts
檔案,並在 test
屬性下,新增相關的測試設定:
// vitest.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
... // 在此新增測試相關的設定
},
})
常見的設定:
- global - 預設為
false
預設使用時,Vitest 並沒有直接提供全域 API,都需要指定 import。如果要把 API 暴露在全域,可以新增 globals: true
:
export default defineConfig({
test: {
...,
globals: true, // 當 API 調用時,不需要再指定引入
},
})
為了讓全域 API 可以支援 TypeScript,需要將 vitest/globals
添加到 tsconfig.json
中的 types
的選項中:
// tsconfig.json
{
"compilerOptions": {
"types": ["vitest/globals"]
}
}
- environment - 預設為
node
測試的執行環境,如果是寫前端,可以使用 jsdom 或 happy-dom:
export default defineConfig({
test: {
...,
environment: "jsdom",
},
})
[補充] > environmentMatchGlobs 可以針對不同檔案跑在不同環境上。
[補充]
如果專案有使用 Vite,Vitest 會自動讀取根目錄的vite.config.ts
,可與 Vite 共用統一的設定檔。如果想配置不同設定,可以另外新增vitest.config.ts
,該檔案優先級為最高。
更多設定可參考 @Configuring Vitest
測試檔案名規則
測試檔案文件名,需要包含 .test.
或 .spec.
,例如:sum.test.js
。
運行測試
在開發環境下預設為監聽模式(watch mode),當修改源程式碼或測試文件時,只會自動重新運行相關的測試。
npm run test
測試覆蓋率 - Coverage
安裝套件
要覆蓋率報告,需要另外安裝相應套件包:
# For v8
npm i -D @vitest/coverage-v8
# For istanbul
npm i -D @vitest/coverage-istanbul
常用設定
provider
- 覆蓋率報告的提供者,預設是 v8reporter
- 覆蓋率報告輸出的類型reportsDirectory
- 覆蓋率報告檔案的位置,預設是在根目錄創建一個coverage
的資料夾存放
// vitest.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
coverage: {
provider: 'v8', // 支援 istanbul 或自定義
reporter: ["json", "html"],
reportsDirectory: "./tests/unit/coverage"
},
},
...
})
更多覆蓋率報告的設定可參考 @Vitest Coverage
產生覆蓋率報告
npx vitest --coverage
VS Code Extension
如果不習慣用終端機下指令,推薦安裝官方 VScode 套件 - Vitest,錯誤會直接顯示 VScode 上。