測試上下文
受到 Playwright Fixtures 的啟發,Vitest 的測試上下文允許您定義可在測試中使用的工具、狀態和測試夾具。
用法
每個測試回調函數的第一個參數都是一個測試上下文。
import { it } from 'vitest';
it('should work', ctx => {
// 打印測試名稱
console.log(ctx.task.name);
});
內建測試上下文
context.task
一個唯讀的物件,包含關於測試的元數據。
context.expect
綁定到當前測試的 expect
API:
import { it } from 'vitest';
it('math is easy', ({ expect }) => {
expect(2 + 2).toBe(4);
});
這個 API 對於並行執行快照測試非常有用,因為全域 expect 無法追蹤它們:
import { it } from 'vitest';
it.concurrent('math is easy', ({ expect }) => {
expect(2 + 2).toMatchInlineSnapshot();
});
it.concurrent('math is hard', ({ expect }) => {
expect(2 * 2).toMatchInlineSnapshot();
});
context.skip
跳過後續的測試執行,並將測試標記為跳過:
import { expect, it } from 'vitest';
it('math is hard', ({ skip }) => {
skip();
expect(2 + 2).toBe(5);
});
擴充測試上下文
Vitest 提供了兩種方式來幫助您擴充測試上下文。
test.extend
WARNING
此 API 自 Vitest 0.32.3 起可用。
與 Playwright 類似,您可以使用此方法定義您自己的 test
API,其中包含自訂的測試夾具,並在任何地方複用它。
例如,我們首先使用兩個測試夾具 todos
和 archive
建立 myTest
。
// my-test.ts
import { test } from 'vitest';
const todos = [];
const archive = [];
export const myTest = test.extend({
todos: async ({ task }, use) => {
// 在每個測試函數之前設定夾具
todos.push(1, 2, 3);
// 使用夾具數值
await use(todos);
// 在每個測試函數之後清理夾具
todos.length = 0;
},
archive,
});
然後我們可以導入並使用它。
import { expect } from 'vitest';
import { myTest } from './my-test.ts';
myTest('add items to todos', ({ todos }) => {
expect(todos.length).toBe(3);
todos.add(4);
expect(todos.length).toBe(4);
});
myTest('move items from todos to archive', ({ todos, archive }) => {
expect(todos.length).toBe(3);
expect(archive.length).toBe(0);
archive.push(todos.pop());
expect(todos.length).toBe(2);
expect(archive.length).toBe(1);
});
我們還可以透過擴充 myTest
來新增更多測試夾具或覆蓋現有的測試夾具。
export const myTest2 = myTest.extend({
settings: {
// ...
},
});
夾具初始化
Vitest 執行器將根據使用情況,智能地初始化您的夾具並將它們注入至測試上下文中。
import { test } from 'vitest';
async function todosFn({ task }, use) {
await use([1, 2, 3]);
}
const myTest = test.extend({
todos: todosFn,
archive: [],
});
// todosFn 不會執行
myTest('', () => {});
myTest('', ({ archive }) => {});
// todosFn 會執行
myTest('', ({ todos }) => {});
WARNING
當使用帶有測試夾具的 test.extend()
時,您應該始終使用物件解構模式 { todos }
來訪問夾具函數和測試函數中的上下文。
TypeScript
要為所有自訂上下文提供夾具類型,您可以將夾具類型作為泛型傳入。
interface MyFixtures {
todos: number[];
archive: number[];
}
const myTest = test.extend<MyFixtures>({
todos: [],
archive: [],
});
myTest('', context => {
expectTypeOf(context.todos).toEqualTypeOf<number[]>();
expectTypeOf(context.archive).toEqualTypeOf<number[]>();
});
beforeEach
和 afterEach
每個測試的上下文都不同。您可以在 beforeEach
和 afterEach
鉤子中存取和擴充它們。
import { beforeEach, it } from 'vitest';
beforeEach(async context => {
// 擴充上下文
context.foo = 'bar';
});
it('should work', ({ foo }) => {
console.log(foo); // 'bar'
});
TypeScript
要為所有自訂上下文提供屬性類型,您可以透過添加以下內容聚合 TestContext
類型
declare module 'vitest' {
export interface TestContext {
foo?: string;
}
}
如果您只想為特定的 beforeEach
、afterEach
、it
和 test
鉤子提供屬性類型,您可以將類型作為泛型傳遞。
interface LocalTestContext {
foo: string;
}
beforeEach<LocalTestContext>(async context => {
// context 的類型是 'TestContext & LocalTestContext'
context.foo = 'bar';
});
it<LocalTestContext>('should work', ({ foo }) => {
// foo 的類型是 'string'
console.log(foo); // 'bar'
});