测试上下文
受 Playwright Fixtures 的启发,Vitest 的测试上下文允许您定义可以在测试中使用的工具、状态和夹具。
用法
每个测试回调的第一个参数都是一个测试上下文。
import { } from 'vitest'
('should work', () => {
// prints name of the test
.(..)
})
内置测试上下文
context.task
包含有关测试的元数据的只读对象。
context.expect
绑定到当前测试的 expect
API
import { } from 'vitest'
('math is easy', ({ }) => {
(2 + 2).(4)
})
此 API 对于并发运行快照测试很有用,因为全局 expect 无法跟踪它们
import { } from 'vitest'
.('math is easy', ({ }) => {
(2 + 2).()
})
.('math is hard', ({ }) => {
(2 * 2).()
})
context.skip
跳过后续测试执行并将测试标记为跳过
import { expect, it } from 'vitest'
it('math is hard', ({ skip }) => {
skip()
expect(2 + 2).toBe(5)
})
扩展测试上下文
Vitest 提供两种不同的方法来帮助您扩展测试上下文。
test.extend
警告
此 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 ({}, use) => {
// setup the fixture before each test function
todos.push(1, 2, 3)
// use the fixture value
await use(todos)
// cleanup the fixture after each test function
todos.length = 0
},
archive
})
然后我们可以导入并使用它。
import { expect } from 'vitest'
import { myTest } from './my-test.js'
myTest('add items to todos', ({ todos }) => {
expect(todos.length).toBe(3)
todos.push(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 will not run
myTest('', () => {})
myTest('', ({ archive }) => {})
// todosFn will run
myTest('', ({ todos }) => {})
警告
在使用 test.extend()
和夹具时,您应该始终使用对象解构模式 { todos }
在夹具函数和测试函数中访问上下文。
自动夹具
警告
此功能自 Vitest 1.3.0 起可用。
Vitest 还支持夹具的元组语法,允许您为每个夹具传递选项。例如,您可以使用它来显式初始化夹具,即使它没有在测试中使用。
import { test as base } from 'vitest'
const test = base.extend({
fixture: [
async ({}, use) => {
// this function will run
setup()
await use()
teardown()
},
{ auto: true } // Mark as an automatic fixture
],
})
test('', () => {})
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) => {
// extend 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) => {
// typeof context is 'TestContext & LocalTestContext'
context.foo = 'bar'
})
it<LocalTestContext>('should work', ({ foo }) => {
// typeof foo is 'string'
console.log(foo) // 'bar'
})