Vitest 3.2 發佈!
2025 年 6 月 2 日
Vitest 3.2 專注於瀏覽器模式(Browser Mode)和 TypeScript 支援的改進。此版本亦包含一些新的實用方法、設定選項,並廢棄了 workspace
設定,改為使用 projects
。
workspace
已廢棄
為了簡化設定,團隊決定廢棄獨立的 vitest.workspace
檔案,並建議僅在根設定中使用 projects
選項。這也簡化了全域選項的設定方式(因為當您沒有根設定時,無需猜測如何添加報告器)。
我們還決定廢棄 workspace
這個名稱,因為它與其他工具(例如 PNPM)衝突,這些工具透過此選項提供 monorepo 支援。Vitest 不會以獨立的 CWD
執行這些專案,而是將它們視為子 Vitest。這也讓我們有更多空間,能在不影響其他工具的情況下,為 monorepo 提出更好的解決方案。
此選項將在未來的主版本中完全移除,並由 projects
取代。在此之前,如果使用了 workspace
功能,Vitest 將會顯示警告。
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
// "test.workspace" 現已改為 "test.projects"
workspace: [
projects: [
{ test: { name: "Unit" } },
{ test: { name: "Integration" } },
],
},
});
註釋 API
新的註釋 API 允許您為任何測試加入自訂訊息和附件。這些註釋在 UI、HTML、junit、tap 和 GitHub Actions 報告器中可見。如果測試失敗,Vitest 還會在 CLI 中顯示相關註釋。

作用域固定裝置(Scoped Fixtures)
test.extend
固定裝置現在可以指定 scope
選項:file
或 worker
。
const test = baseTest.extend({
db: [
async ({}, use) => {
// ...setup
await use(db);
await db.close();
},
{ scope: 'worker' },
],
});
檔案固定裝置(file fixture)類似於在檔案頂層使用 beforeAll
和 afterAll
,但如果該固定裝置未在任何測試中使用,則不會被呼叫。
工作者固定裝置(worker fixture)每個工作者只會初始化一次,但請注意,預設情況下 Vitest 會為每個測試建立一個工作者,因此您需要關閉隔離(isolation)才能發揮其效益。
自訂專案名稱顏色
現在使用 projects
時,您可以設定自訂的顏色:
設定範例
export default defineConfig({
test: {
projects: [
{
test: {
name: {
label: 'unit',
color: 'red',
},
},
},
{
test: {
name: {
label: 'browser',
color: 'green',
},
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
},
},
],
},
})

自訂瀏覽器定位器 API
內建的定位器可能不足以滿足您應用程式的需求。現在,我們建議使用新的 locators.extend
API 來擴充定位器,而不是改用 CSS 並失去 Vitest 透過其定位器 API 提供的重試保護。
import { locators } from '@vitest/browser/context';
locators.extend({
getByCommentsCount(count: number) {
return `.comments :text("${count} comments")`;
},
});
返回一個 Playwright 定位器字串來建構一個新的定位器。請注意,如果存在父定位器,此方法返回的字串將會被限定在父定位器的範圍內。
現在您可以直接在 page
或任何其他定位器上呼叫 getByCommentsCount
:
await expect.element(page.getByCommentsCount(1)).toBeVisible();
await expect
.element(
page.getByRole('article', { name: 'Hello World' }).getByCommentsCount(1)
)
.toBeVisible();
如果此方法返回一個字串,則回傳值將被轉換為定位器,因此您可以繼續鏈式呼叫:
page
.getByRole('article', { name: 'Hello World' })
.getByCommentsCount(1)
.getByText('comments');
此方法可以存取目前的定位器上下文(如果有的話)。例如,如果方法在 page
上呼叫,則上下文將指向 page
,因此您可以在內部鏈式呼叫所有定位器方法:
import { locators } from '@vitest/browser/context';
import type { Locator } from '@vitest/browser/context';
locators.extend({
getByCommentsCount(this: Locator, count: number) {
return this.getByRole('comment').and(this.getByText(`${count} comments`));
},
});
存取上下文也允許您呼叫定位器的一般方法來定義自訂使用者事件:
import { locators, page } from '@vitest/browser/context';
import type { Locator } from '@vitest/browser/context';
locators.extend({
clickAndFill(this: Locator, text: string) {
await this.click();
await this.fill(text);
},
});
await page.getByRole('textbox').clickAndFill('Hello World');
請參閱 locators.extend
API 以獲取更多資訊。
vi.spyOn
和 vi.fn
中的顯式資源管理
在支援顯式資源管理的環境中,您可以使用 using
而不是 const
,以便在包含區塊退出時自動呼叫任何模擬函式上的 mockRestore
。這對於被監聽的方法特別有用:
it('calls console.log', () => {
using spy = vi.spyOn(console, 'log').mockImplementation(() => {})
debug('message')
expect(spy).toHaveBeenCalled()
})
// console.log is restored here
測試 signal
API
Vitest 現在為測試主體提供了一個 AbortSignal
物件。您可以使用它來停止任何支援此 Web API 的資源。
當測試逾時、另一個測試失敗且 --bail
標誌設定為非零值,或使用者在終端機中按下 Ctrl+C 時,訊號會被中止。
例如,當測試中斷時,您可以停止 fetch
請求:
it('stop request when test times out', async ({ signal }) => {
await fetch('/heavy-resource', { signal });
}, 2000);
覆蓋率 V8 AST 感知重映射
Vitest 現在使用由 Vitest 維護者之一 AriPerkkio 開發的 ast-v8-to-istanbul
套件。這使得 v8 覆蓋率報告與 istanbul 一致,同時提供更好的效能。透過將 coverage.experimentalAstAwareRemapping
設定為 true
來啟用此功能。
我們計劃在下一個主版本中將此設定為預設的重映射模式。舊的 v8-to-istanbul
將會被完全移除。歡迎加入討論:https://github.com/vitest-dev/vitest/issues/7928。
watchTriggerPatterns
選項
當您編輯檔案時,Vitest 足夠智慧,只會重新執行匯入此檔案的測試。不幸的是,Vitest 靜態分析只會識別靜態和動態的 import
語句。如果您正在讀取檔案或啟動獨立的程序,Vitest 將會忽略相關檔案的變更。
使用 watchTriggerPatterns
選項,您可以根據變更的檔案來配置要重新執行的測試。例如,為了在範本變更時始終重新執行 mailers
測試,請添加一個觸發模式:
export default defineConfig({
test: {
watchTriggerPatterns: [
{
pattern: /^src\/templates\/(.*)\.(ts|html|txt)$/,
testsToRun: (file, match) => {
return `api/tests/mailers/${match[2]}.test.ts`;
},
},
],
},
});
新的多用途 Matchers
類型
Vitest 現在有一個 Matchers
類型,您可以擴充它以在單一位置為所有自訂匹配器加入類型支援。此類型影響所有這些使用案例:
expect().to*
expect.to*
expect.extend({ to* })
例如,要有一個類型安全的 toBeFoo
匹配器,您可以這樣寫:
import { expect } from 'vitest';
interface CustomMatchers<R = unknown> {
toBeFoo: (arg: string) => R;
}
declare module 'vitest' {
interface Matchers<T = any> extends CustomMatchers<T> {}
}
expect.extend({
toBeFoo(actual, arg) {
// ^?
// ... implementation
return {
pass: true,
message: () => '',
};
},
});
expect('foo').toBeFoo('foo');
expect.toBeFoo('foo');
sequence.groupOrder
新的 sequence.groupOrder
選項控制在使用多個專案時,專案執行測試的順序。
- 具有相同群組順序編號的專案將一起執行,群組從最低到最高執行。
- 如果您未設定此選項,所有專案將並行執行。
- 如果多個專案使用相同的群組順序,它們將會並行執行。
範例
考慮這個範例:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
projects: [
{
test: {
name: 'slow',
sequence: {
groupOrder: 0,
},
},
},
{
test: {
name: 'fast',
sequence: {
groupOrder: 0,
},
},
},
{
test: {
name: 'flaky',
sequence: {
groupOrder: 1,
},
},
},
],
},
});
這些專案中的測試將按此順序執行:
0. slow |
|> 一起執行
0. fast |
1. flaky |> 在 slow 和 fast 之後單獨執行
完整的變更列表請參閱 Vitest 3.2 變更日誌。