功能
- 整合 Vite 的配置、轉換工具、解析器及外掛。
- 測試執行時,沿用應用程式的既有設定。
- 智慧型即時監控模式,提供類似測試 HMR 的體驗。
- 支援 Vue、React、Svelte、Lit、Marko 等框架的元件測試。
- 原生支援 TypeScript 及 JSX。
- 優先採用 ESM,並支援頂層 await。
- 透過 Tinypool 實現 Worker 多執行緒。
- 透過 Tinybench 支援基準測試。
- 提供套件與測試的篩選、逾時設定及平行執行功能。
- 支援工作區。
- 提供與 Jest 相容的快照功能。
- 內建 Chai 用於斷言,並提供與 Jest expect 相容的 API。
- 內建 Tinyspy 用於模擬功能。
- 支援 happy-dom 或 jsdom 進行 DOM 模擬。
- 提供 瀏覽器模式,可在瀏覽器環境中執行元件測試。
- 程式碼覆蓋率支援 v8 或 istanbul。
- 類似 Rust 的原始碼內建測試。
- 透過 expect-type 進行型別測試。
- 支援測試分片。
測試、開發與建置間的共用配置
Vitest 整合 Vite 的配置、轉換工具、解析器及外掛,確保測試執行時能沿用應用程式的既有設定。
詳情請參閱 配置 Vitest。
監控模式
$ vitest
當您修改原始碼或測試檔案時,Vitest 會智慧地分析模組依賴圖,並僅重新執行相關測試,提供類似 Vite HMR 的即時回饋!
vitest
在開發環境中預設以 watch mode
啟動;而在 CI 環境中(當 process.env.CI
存在時),則會智慧地切換至 run mode
。您亦可透過 vitest watch
或 vitest run
明確指定所需的模式。
使用 --standalone
旗標啟動 Vitest,使其在背景執行。在此模式下,Vitest 不會立即執行任何測試,直到相關檔案發生變更。若原始碼變動,Vitest 將等待匯入該原始碼的測試執行完畢後,才會觸發測試。
開箱即用的常見 Web 慣例支援
原生支援 ES 模組、TypeScript、JSX 及 PostCSS。
執行緒
預設情況下,Vitest 會利用 node:child_process
搭配 Tinypool(Piscina 的輕量級分支),在多個程序中平行執行測試檔案,以提升測試速度。若您希望進一步加速測試套件,可考慮啟用 --pool=threads
,改用 node:worker_threads
執行測試(請注意,部分套件可能不適用於此設定)。
若需在單一執行緒或程序中執行測試,請參考 poolOptions
。
Vitest 也會隔離每個檔案的執行環境,確保一個檔案中的環境變動不會影響其他檔案。此隔離功能可透過傳遞 --no-isolate
參數來停用(以正確性換取執行效能)。
測試篩選
Vitest 提供多種方法來縮小要執行的測試範圍,以加快測試速度,讓您可以專注於開發。
詳情請參閱 測試篩選。
平行執行測試
在連續測試中,使用 .concurrent
標記可使其平行啟動。
import { describe, it } from 'vitest';
// 這兩個標記為 concurrent 的測試將同時啟動
describe('suite', () => {
it('serial test', async () => {
/* ... */
});
it.concurrent('concurrent test 1', async ({ expect }) => {
/* ... */
});
it.concurrent('concurrent test 2', async ({ expect }) => {
/* ... */
});
});
若您在測試套件上使用 .concurrent
,則該套件內的所有測試都將平行啟動。
import { describe, it } from 'vitest';
// 此套件中的所有測試都將並列啟動
describe.concurrent('suite', () => {
it('concurrent test 1', async ({ expect }) => {
/* ... */
});
it('concurrent test 2', async ({ expect }) => {
/* ... */
});
it.concurrent('concurrent test 3', async ({ expect }) => {
/* ... */
});
});
您還可以將 .skip
、.only
和 .todo
與平行的套件和測試一同使用。詳情請參閱 API 參考。
WARNING
執行平行測試時,快照與斷言必須使用來自本地 測試上下文 的 expect
,以確保正確識別相關測試。
快照
支援與 Jest 相容 的快照功能。
import { expect, it } from 'vitest';
it('renders correctly', () => {
const result = render();
expect(result).toMatchSnapshot();
});
詳情請參閱 快照。
Chai 與 Jest expect
相容性
內建 Chai 用於斷言,並提供與 Jest expect
相容的 API。
請注意,若您使用新增匹配器的第三方函式庫,將 test.globals
設定為 true
將提供更好的相容性。
模擬功能
內建 Tinyspy 用於模擬功能,並在 vi
物件上提供與 jest
相容的 API。
import { expect, vi } from 'vitest';
const fn = vi.fn();
fn('hello', 1);
expect(vi.isMockFunction(fn)).toBe(true);
expect(fn.mock.calls[0]).toEqual(['hello', 1]);
fn.mockImplementation((arg: string) => arg);
fn('world', 2);
expect(fn.mock.results[1].value).toBe('world');
Vitest 支援 happy-dom 或 jsdom 用於模擬 DOM 及瀏覽器 API。這些函式庫不隨 Vitest 一同提供,您需要另外安裝:
$ npm i -D happy-dom
# 或
$ npm i -D jsdom
安裝後,請在您的設定檔中更改 environment
選項:
// vitest.config.ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'happy-dom', // 或 'jsdom', 'node'
},
});
詳情請參閱 模擬功能。
覆蓋率
Vitest 支援透過 v8
進行原生程式碼覆蓋率,以及透過 istanbul
進行檢測工具化程式碼覆蓋率。
{
"scripts": {
"test": "vitest",
"coverage": "vitest run --coverage"
}
}
詳情請參閱 覆蓋率。
原始碼內建測試
Vitest 亦提供一種在原始碼中執行測試的方法,與實作程式碼並存,類似於 Rust 的模組測試。
此方法使測試與實作共享相同的閉包,並能在不匯出的情況下測試私有狀態。同時,它也縮短了開發的反饋循環。
// src/index.ts
// 實作
export function add(...args: number[]): number {
return args.reduce((a, b) => a + b, 0);
}
// 原始碼內建測試套件
if (import.meta.vitest) {
const { it, expect } = import.meta.vitest;
it('add', () => {
expect(add()).toBe(0);
expect(add(1)).toBe(1);
expect(add(1, 2, 3)).toBe(6);
});
}
詳情請參閱 原始碼內建測試。
基準測試 實驗性
您可以使用 bench
函式透過 Tinybench 進行基準測試,以比較效能結果。
import { bench, describe } from 'vitest';
describe('sort', () => {
bench('normal', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});
bench('reverse', () => {
const x = [1, 5, 4, 2, 3];
x.reverse().sort((a, b) => {
return a - b;
});
});
});
型別測試 實驗性
您可以編寫測試來捕捉型別回歸。Vitest 隨附 expect-type
套件,為您提供類似且易於理解的 API。
import { assertType, expectTypeOf, test } from 'vitest';
import { mount } from './mount.js';
test('my types work properly', () => {
expectTypeOf(mount).toBeFunction();
expectTypeOf(mount).parameter(0).toMatchTypeOf<{ name: string }>();
// @ts-expect-error name is a string
assertType(mount({ name: 42 }));
});
分片
使用 --shard
和 --reporter=blob
參數可在不同的機器上執行測試。 所有測試和覆蓋率結果都可以在 CI 管道結束時使用 --merge-reports
命令進行合併:
vitest --shard=1/2 --reporter=blob
vitest --shard=2/2 --reporter=blob
vitest --merge-reports --reporter=junit --coverage.reporter=text
有關更多資訊,請參閱 提升效能 | 分片
。
環境變數
Vitest 會自動載入以 VITE_
為前綴的 .env
檔案中的環境變數,以確保與前端相關測試的相容性,並遵循 Vite 既定的慣例。若需載入 .env
檔案中的所有環境變數,您可以使用從 vite
匯入的 loadEnv
方法:
import { loadEnv } from 'vite';
import { defineConfig } from 'vitest/config';
export default defineConfig(({ mode }) => ({
test: {
// mode 定義了如果存在,應選擇哪個 ".env.{mode}" 檔案
env: loadEnv(mode, process.cwd(), ''),
},
}));