Test API Reference
The following types are used in the type signatures below
type Awaitable<T> = T | PromiseLike<T>
type TestFunction = () => Awaitable<void>
interface TestOptions {
/**
* Will fail the test if it takes too long to execute
*/
timeout?: number
/**
* Will retry the test specific number of times if it fails
*
* @default 0
*/
retry?: number
/**
* Will repeat the same test several times even if it fails each time
* If you have "retry" option and it fails, it will use every retry in each cycle
* Useful for debugging random failings
*
* @default 0
*/
repeats?: number
}
type Awaitable<T> = T | PromiseLike<T>
type TestFunction = () => Awaitable<void>
interface TestOptions {
/**
* Will fail the test if it takes too long to execute
*/
timeout?: number
/**
* Will retry the test specific number of times if it fails
*
* @default 0
*/
retry?: number
/**
* Will repeat the same test several times even if it fails each time
* If you have "retry" option and it fails, it will use every retry in each cycle
* Useful for debugging random failings
*
* @default 0
*/
repeats?: number
}
When a test function returns a promise, the runner will wait until it is resolved to collect async expectations. If the promise is rejected, the test will fail.
TIP
In Jest, TestFunction
can also be of type (done: DoneCallback) => void
. If this form is used, the test will not be concluded until done
is called. You can achieve the same using an async
function, see the Migration guide Done Callback section.
test
Type:
(name: string | Function, fn: TestFunction, timeout?: number | TestOptions) => void
Alias:
it
test
defines a set of related expectations. It receives the test name and a function that holds the expectations to test.Optionally, you can provide a timeout (in milliseconds) for specifying how long to wait before terminating. The default is 5 seconds, and can be configured globally with testTimeout
tsimport { expect, test } from 'vitest' test('should work as expected', () => { expect(Math.sqrt(4)).toBe(2) })
import { expect, test } from 'vitest' test('should work as expected', () => { expect(Math.sqrt(4)).toBe(2) })
test.extend
Type:
<T extends Record<string, any>>(fixtures: Fixtures<T>): TestAPI<ExtraContext & T>
Alias:
it.extend
Version: Vitest 0.32.3
Use
test.extend
to extend the test context with custom fixtures. This will return a newtest
and it's also extendable, so you can compose more fixtures or override existing ones by extending it as you need. See Extend Test Context for more information.tsimport { expect, test } from 'vitest' const todos = [] const archive = [] const myTest = test.extend({ todos: async ({ task }, use) => { todos.push(1, 2, 3) await use(todos) todos.length = 0 }, archive }) myTest('add item', ({ todos }) => { expect(todos.length).toBe(3) todos.push(4) expect(todos.length).toBe(4) })
import { expect, test } from 'vitest' const todos = [] const archive = [] const myTest = test.extend({ todos: async ({ task }, use) => { todos.push(1, 2, 3) await use(todos) todos.length = 0 }, archive }) myTest('add item', ({ todos }) => { expect(todos.length).toBe(3) todos.push(4) expect(todos.length).toBe(4) })
test.skip
Type:
(name: string | Function, fn: TestFunction, timeout?: number | TestOptions) => void
Alias:
it.skip
If you want to skip running certain tests, but you don't want to delete the code due to any reason, you can use
test.skip
to avoid running them.tsimport { assert, test } from 'vitest' test.skip('skipped test', () => { // Test skipped, no error assert.equal(Math.sqrt(4), 3) })
import { assert, test } from 'vitest' test.skip('skipped test', () => { // Test skipped, no error assert.equal(Math.sqrt(4), 3) })
test.skipIf
Type:
(condition: any) => Test
Alias:
it.skipIf
In some cases you might run tests multiple times with different environments, and some of the tests might be environment-specific. Instead of wrapping the test code with
if
, you can usetest.skipIf
to skip the test whenever the condition is truthy.tsimport { assert, test } from 'vitest' const isDev = process.env.NODE_ENV === 'development' test.skipIf(isDev)('prod only test', () => { // this test only runs in production })
import { assert, test } from 'vitest' const isDev = process.env.NODE_ENV === 'development' test.skipIf(isDev)('prod only test', () => { // this test only runs in production })
WARNING
You cannot use this syntax, when using Vitest as type checker.
test.runIf
Type:
(condition: any) => Test
Alias:
it.runIf
Opposite of test.skipIf.
tsimport { assert, test } from 'vitest' const isDev = process.env.NODE_ENV === 'development' test.runIf(isDev)('dev only test', () => { // this test only runs in development })
import { assert, test } from 'vitest' const isDev = process.env.NODE_ENV === 'development' test.runIf(isDev)('dev only test', () => { // this test only runs in development })
WARNING
You cannot use this syntax, when using Vitest as type checker.
test.only
Type:
(name: string | Function, fn: TestFunction, timeout?: number) => void
Alias:
it.only
Use
test.only
to only run certain tests in a given suite. This is useful when debugging.Optionally, you can provide a timeout (in milliseconds) for specifying how long to wait before terminating. The default is 5 seconds, and can be configured globally with testTimeout.
tsimport { assert, test } from 'vitest' test.only('test', () => { // Only this test (and others marked with only) are run assert.equal(Math.sqrt(4), 2) })
import { assert, test } from 'vitest' test.only('test', () => { // Only this test (and others marked with only) are run assert.equal(Math.sqrt(4), 2) })
Sometimes it is very useful to run
only
tests in a certain file, ignoring all other tests from the whole test suite, which pollute the output.In order to do that run
vitest
with specific file containing the tests in question.# vitest interesting.test.ts
# vitest interesting.test.ts
test.concurrent
Type:
(name: string | Function, fn: TestFunction, timeout?: number) => void
Alias:
it.concurrent
test.concurrent
marks consecutive tests to be run in parallel. It receives the test name, an async function with the tests to collect, and an optional timeout (in milliseconds).tsimport { describe, test } from 'vitest' // The two tests marked with concurrent will be run in parallel describe('suite', () => { test('serial test', async () => { /* ... */ }) test.concurrent('concurrent test 1', async () => { /* ... */ }) test.concurrent('concurrent test 2', async () => { /* ... */ }) })
import { describe, test } from 'vitest' // The two tests marked with concurrent will be run in parallel describe('suite', () => { test('serial test', async () => { /* ... */ }) test.concurrent('concurrent test 1', async () => { /* ... */ }) test.concurrent('concurrent test 2', async () => { /* ... */ }) })
test.skip
,test.only
, andtest.todo
works with concurrent tests. All the following combinations are valid:tstest.concurrent(/* ... */) test.skip.concurrent(/* ... */) // or test.concurrent.skip(/* ... */) test.only.concurrent(/* ... */) // or test.concurrent.only(/* ... */) test.todo.concurrent(/* ... */) // or test.concurrent.todo(/* ... */)
test.concurrent(/* ... */) test.skip.concurrent(/* ... */) // or test.concurrent.skip(/* ... */) test.only.concurrent(/* ... */) // or test.concurrent.only(/* ... */) test.todo.concurrent(/* ... */) // or test.concurrent.todo(/* ... */)
When running concurrent tests, Snapshots and Assertions must use
expect
from the local Test Context to ensure the right test is detected.tstest.concurrent('test 1', async ({ expect }) => { expect(foo).toMatchSnapshot() }) test.concurrent('test 2', async ({ expect }) => { expect(foo).toMatchSnapshot() })
test.concurrent('test 1', async ({ expect }) => { expect(foo).toMatchSnapshot() }) test.concurrent('test 2', async ({ expect }) => { expect(foo).toMatchSnapshot() })
WARNING
You cannot use this syntax, when using Vitest as type checker.
test.todo
Type:
(name: string | Function) => void
Alias:
it.todo
Use
test.todo
to stub tests to be implemented later. An entry will be shown in the report for the tests so you know how many tests you still need to implement.ts// An entry will be shown in the report for this test test.todo('unimplemented test')
// An entry will be shown in the report for this test test.todo('unimplemented test')
test.fails
Type:
(name: string | Function, fn: TestFunction, timeout?: number) => void
Alias:
it.fails
Use
test.fails
to indicate that an assertion will fail explicitly.tsimport { expect, test } from 'vitest' function myAsyncFunc() { return new Promise(resolve => resolve(1)) } test.fails('fail test', async () => { await expect(myAsyncFunc()).rejects.toBe(1) })
import { expect, test } from 'vitest' function myAsyncFunc() { return new Promise(resolve => resolve(1)) } test.fails('fail test', async () => { await expect(myAsyncFunc()).rejects.toBe(1) })
WARNING
You cannot use this syntax, when using Vitest as type checker.
test.each
Type:
(cases: ReadonlyArray<T>, ...args: any[]) => void
Alias:
it.each
Use
test.each
when you need to run the same test with different variables. You can inject parameters with printf formatting in the test name in the order of the test function parameters.%s
: string%d
: number%i
: integer%f
: floating point value%j
: json%o
: object%#
: index of the test case%%
: single percent sign ('%')
tstest.each([ [1, 1, 2], [1, 2, 3], [2, 1, 3], ])('add(%i, %i) -> %i', (a, b, expected) => { expect(a + b).toBe(expected) }) // this will return // ✓ add(1, 1) -> 2 // ✓ add(1, 2) -> 3 // ✓ add(2, 1) -> 3
test.each([ [1, 1, 2], [1, 2, 3], [2, 1, 3], ])('add(%i, %i) -> %i', (a, b, expected) => { expect(a + b).toBe(expected) }) // this will return // ✓ add(1, 1) -> 2 // ✓ add(1, 2) -> 3 // ✓ add(2, 1) -> 3
You can also access object properties with
$
prefix, if you are using objects as arguments:tstest.each([ { a: 1, b: 1, expected: 2 }, { a: 1, b: 2, expected: 3 }, { a: 2, b: 1, expected: 3 }, ])('add($a, $b) -> $expected', ({ a, b, expected }) => { expect(a + b).toBe(expected) }) // this will return // ✓ add(1, 1) -> 2 // ✓ add(1, 2) -> 3 // ✓ add(2, 1) -> 3
test.each([ { a: 1, b: 1, expected: 2 }, { a: 1, b: 2, expected: 3 }, { a: 2, b: 1, expected: 3 }, ])('add($a, $b) -> $expected', ({ a, b, expected }) => { expect(a + b).toBe(expected) }) // this will return // ✓ add(1, 1) -> 2 // ✓ add(1, 2) -> 3 // ✓ add(2, 1) -> 3
You can also access Object attributes with
.
, if you are using objects as arguments:tstest.each` a | b | expected ${{ val: 1 }} | ${'b'} | ${'1b'} ${{ val: 2 }} | ${'b'} | ${'2b'} ${{ val: 3 }} | ${'b'} | ${'3b'} `('add($a.val, $b) -> $expected', ({ a, b, expected }) => { expect(a.val + b).toBe(expected) }) // this will return // ✓ add(1, b) -> 1b // ✓ add(2, b) -> 2b // ✓ add(3, b) -> 3b
test.each` a | b | expected ${{ val: 1 }} | ${'b'} | ${'1b'} ${{ val: 2 }} | ${'b'} | ${'2b'} ${{ val: 3 }} | ${'b'} | ${'3b'} `('add($a.val, $b) -> $expected', ({ a, b, expected }) => { expect(a.val + b).toBe(expected) }) // this will return // ✓ add(1, b) -> 1b // ✓ add(2, b) -> 2b // ✓ add(3, b) -> 3b
Starting from Vitest 0.25.3, you can also use template string table.
- First row should be column names, separated by
|
; - One or more subsequent rows of data supplied as template literal expressions using
${value}
syntax.
tstest.each` a | b | expected ${1} | ${1} | ${2} ${'a'} | ${'b'} | ${'ab'} ${[]} | ${'b'} | ${'b'} ${{}} | ${'b'} | ${'[object Object]b'} ${{ asd: 1 }} | ${'b'} | ${'[object Object]b'} `('returns $expected when $a is added $b', ({ a, b, expected }) => { expect(a + b).toBe(expected) })
test.each` a | b | expected ${1} | ${1} | ${2} ${'a'} | ${'b'} | ${'ab'} ${[]} | ${'b'} | ${'b'} ${{}} | ${'b'} | ${'[object Object]b'} ${{ asd: 1 }} | ${'b'} | ${'[object Object]b'} `('returns $expected when $a is added $b', ({ a, b, expected }) => { expect(a + b).toBe(expected) })
If you want to have access to
TestContext
, usedescribe.each
with a single test.
TIP
Vitest processes $values
with chai format
method. If the value is too truncated, you can increase chaiConfig.truncateThreshold in your config file.
WARNING
You cannot use this syntax, when using Vitest as type checker.
bench
- Type:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
bench
defines a benchmark. In Vitest terms benchmark is a function that defines a series of operations. Vitest runs this function multiple times to display different performance results.
Vitest uses tinybench
library under the hood, inheriting all its options that can be used as a third argument.
import { bench } from 'vitest'
bench('normal sorting', () => {
const x = [1, 5, 4, 2, 3]
x.sort((a, b) => {
return a - b
})
}, { time: 1000 })
import { bench } from 'vitest'
bench('normal sorting', () => {
const x = [1, 5, 4, 2, 3]
x.sort((a, b) => {
return a - b
})
}, { time: 1000 })
export interface Options {
/**
* time needed for running a benchmark task (milliseconds)
* @default 500
*/
time?: number
/**
* number of times that a task should run if even the time option is finished
* @default 10
*/
iterations?: number
/**
* function to get the current timestamp in milliseconds
*/
now?: () => number
/**
* An AbortSignal for aborting the benchmark
*/
signal?: AbortSignal
/**
* warmup time (milliseconds)
* @default 100ms
*/
warmupTime?: number
/**
* warmup iterations
* @default 5
*/
warmupIterations?: number
/**
* setup function to run before each benchmark task (cycle)
*/
setup?: Hook
/**
* teardown function to run after each benchmark task (cycle)
*/
teardown?: Hook
}
export interface Options {
/**
* time needed for running a benchmark task (milliseconds)
* @default 500
*/
time?: number
/**
* number of times that a task should run if even the time option is finished
* @default 10
*/
iterations?: number
/**
* function to get the current timestamp in milliseconds
*/
now?: () => number
/**
* An AbortSignal for aborting the benchmark
*/
signal?: AbortSignal
/**
* warmup time (milliseconds)
* @default 100ms
*/
warmupTime?: number
/**
* warmup iterations
* @default 5
*/
warmupIterations?: number
/**
* setup function to run before each benchmark task (cycle)
*/
setup?: Hook
/**
* teardown function to run after each benchmark task (cycle)
*/
teardown?: Hook
}
bench.skip
- Type:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
You can use bench.skip
syntax to skip running certain benchmarks.
import { bench } from 'vitest'
bench.skip('normal sorting', () => {
const x = [1, 5, 4, 2, 3]
x.sort((a, b) => {
return a - b
})
})
import { bench } from 'vitest'
bench.skip('normal sorting', () => {
const x = [1, 5, 4, 2, 3]
x.sort((a, b) => {
return a - b
})
})
bench.only
- Type:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
Use bench.only
to only run certain benchmarks in a given suite. This is useful when debugging.
import { bench } from 'vitest'
bench.only('normal sorting', () => {
const x = [1, 5, 4, 2, 3]
x.sort((a, b) => {
return a - b
})
})
import { bench } from 'vitest'
bench.only('normal sorting', () => {
const x = [1, 5, 4, 2, 3]
x.sort((a, b) => {
return a - b
})
})
bench.todo
- Type:
(name: string | Function) => void
Use bench.todo
to stub benchmarks to be implemented later.
import { bench } from 'vitest'
bench.todo('unimplemented test')
import { bench } from 'vitest'
bench.todo('unimplemented test')
describe
When you use test
or bench
in the top level of file, they are collected as part of the implicit suite for it. Using describe
you can define a new suite in the current context, as a set of related tests or benchmarks and other nested suites. A suite lets you organize your tests and benchmarks so reports are more clear.
// basic.spec.ts
// organizing tests
import { describe, expect, test } from 'vitest'
const person = {
isActive: true,
age: 32,
}
describe('person', () => {
test('person is defined', () => {
expect(person).toBeDefined()
})
test('is active', () => {
expect(person.isActive).toBeTruthy()
})
test('age limit', () => {
expect(person.age).toBeLessThanOrEqual(32)
})
})
// basic.spec.ts
// organizing tests
import { describe, expect, test } from 'vitest'
const person = {
isActive: true,
age: 32,
}
describe('person', () => {
test('person is defined', () => {
expect(person).toBeDefined()
})
test('is active', () => {
expect(person.isActive).toBeTruthy()
})
test('age limit', () => {
expect(person.age).toBeLessThanOrEqual(32)
})
})
// basic.bench.ts
// organizing benchmarks
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
})
})
})
// basic.bench.ts
// organizing benchmarks
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
})
})
})
You can also nest describe blocks if you have a hierarchy of tests or benchmarks:
import { describe, expect, test } from 'vitest'
function numberToCurrency(value) {
if (typeof value !== 'number')
throw new Error('Value must be a number')
return value.toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}
describe('numberToCurrency', () => {
describe('given an invalid number', () => {
test('composed of non-numbers to throw error', () => {
expect(() => numberToCurrency('abc')).toThrowError()
})
})
describe('given a valid number', () => {
test('returns the correct currency format', () => {
expect(numberToCurrency(10000)).toBe('10,000.00')
})
})
})
import { describe, expect, test } from 'vitest'
function numberToCurrency(value) {
if (typeof value !== 'number')
throw new Error('Value must be a number')
return value.toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}
describe('numberToCurrency', () => {
describe('given an invalid number', () => {
test('composed of non-numbers to throw error', () => {
expect(() => numberToCurrency('abc')).toThrowError()
})
})
describe('given a valid number', () => {
test('returns the correct currency format', () => {
expect(numberToCurrency(10000)).toBe('10,000.00')
})
})
})
describe.skip
Type:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
Use
describe.skip
in a suite to avoid running a particular describe block.tsimport { assert, describe, test } from 'vitest' describe.skip('skipped suite', () => { test('sqrt', () => { // Suite skipped, no error assert.equal(Math.sqrt(4), 3) }) })
import { assert, describe, test } from 'vitest' describe.skip('skipped suite', () => { test('sqrt', () => { // Suite skipped, no error assert.equal(Math.sqrt(4), 3) }) })
describe.skipIf
Type:
(condition: any) => void
In some cases, you might run suites multiple times with different environments, and some of the suites might be environment-specific. Instead of wrapping the suite with
if
, you can usedescribe.skipIf
to skip the suite whenever the condition is truthy.tsimport { describe, test } from 'vitest' const isDev = process.env.NODE_ENV === 'development' describe.skipIf(isDev)('prod only test', () => { // this test only runs in production })
import { describe, test } from 'vitest' const isDev = process.env.NODE_ENV === 'development' describe.skipIf(isDev)('prod only test', () => { // this test only runs in production })
WARNING
You cannot use this syntax when using Vitest as type checker.
describe.only
Type:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
Use
describe.only
to only run certain suitests// Only this suite (and others marked with only) are run describe.only('suite', () => { test('sqrt', () => { assert.equal(Math.sqrt(4), 3) }) }) describe('other suite', () => { // ... will be skipped })
// Only this suite (and others marked with only) are run describe.only('suite', () => { test('sqrt', () => { assert.equal(Math.sqrt(4), 3) }) }) describe('other suite', () => { // ... will be skipped })
Sometimes it is very useful to run
only
tests in a certain file, ignoring all other tests from the whole test suite, which pollute the output.In order to do that run
vitest
with specific file containing the tests in question.# vitest interesting.test.ts
# vitest interesting.test.ts
describe.concurrent
Type:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
describe.concurrent
in a suite marks every tests as concurrentts// All tests within this suite will be run in parallel describe.concurrent('suite', () => { test('concurrent test 1', async () => { /* ... */ }) test('concurrent test 2', async () => { /* ... */ }) test.concurrent('concurrent test 3', async () => { /* ... */ }) })
// All tests within this suite will be run in parallel describe.concurrent('suite', () => { test('concurrent test 1', async () => { /* ... */ }) test('concurrent test 2', async () => { /* ... */ }) test.concurrent('concurrent test 3', async () => { /* ... */ }) })
.skip
,.only
, and.todo
works with concurrent suites. All the following combinations are valid:tsdescribe.concurrent(/* ... */) describe.skip.concurrent(/* ... */) // or describe.concurrent.skip(/* ... */) describe.only.concurrent(/* ... */) // or describe.concurrent.only(/* ... */) describe.todo.concurrent(/* ... */) // or describe.concurrent.todo(/* ... */)
describe.concurrent(/* ... */) describe.skip.concurrent(/* ... */) // or describe.concurrent.skip(/* ... */) describe.only.concurrent(/* ... */) // or describe.concurrent.only(/* ... */) describe.todo.concurrent(/* ... */) // or describe.concurrent.todo(/* ... */)
When running concurrent tests, Snapshots and Assertions must use expect
from the local Test Context to ensure the right test is detected.
describe.concurrent('suite', () => {
test('concurrent test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot()
})
test('concurrent test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot()
})
})
describe.concurrent('suite', () => {
test('concurrent test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot()
})
test('concurrent test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot()
})
})
WARNING
You cannot use this syntax, when using Vitest as type checker.
describe.sequential
Type:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
describe.sequential
in a suite marks every test as sequential. This is useful if you want to run tests in sequential withindescribe.concurrent
or with the--sequence.concurrent
command option.tsdescribe.concurrent('suite', () => { test('concurrent test 1', async () => { /* ... */ }) test('concurrent test 2', async () => { /* ... */ }) describe.sequential('', () => { test('sequential test 1', async () => { /* ... */ }) test('sequential test 2', async () => { /* ... */ }) }) })
describe.concurrent('suite', () => { test('concurrent test 1', async () => { /* ... */ }) test('concurrent test 2', async () => { /* ... */ }) describe.sequential('', () => { test('sequential test 1', async () => { /* ... */ }) test('sequential test 2', async () => { /* ... */ }) }) })
describe.shuffle
Type:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
Vitest provides a way to run all tests in random order via CLI flag
--sequence.shuffle
or config optionsequence.shuffle
, but if you want to have only part of your test suite to run tests in random order, you can mark it with this flag.tsdescribe.shuffle('suite', () => { test('random test 1', async () => { /* ... */ }) test('random test 2', async () => { /* ... */ }) test('random test 3', async () => { /* ... */ }) }) // order depends on sequence.seed option in config (Date.now() by default)
describe.shuffle('suite', () => { test('random test 1', async () => { /* ... */ }) test('random test 2', async () => { /* ... */ }) test('random test 3', async () => { /* ... */ }) }) // order depends on sequence.seed option in config (Date.now() by default)
.skip
, .only
, and .todo
works with random suites.
WARNING
You cannot use this syntax, when using Vitest as type checker.
describe.todo
Type:
(name: string | Function) => void
Use
describe.todo
to stub suites to be implemented later. An entry will be shown in the report for the tests so you know how many tests you still need to implement.ts// An entry will be shown in the report for this suite describe.todo('unimplemented suite')
// An entry will be shown in the report for this suite describe.todo('unimplemented suite')
describe.each
Type:
(cases: ReadonlyArray<T>, ...args: any[]): (name: string | Function, fn: (...args: T[]) => void, options?: number | TestOptions) => void
Use
describe.each
if you have more than one test that depends on the same data.tsdescribe.each([ { a: 1, b: 1, expected: 2 }, { a: 1, b: 2, expected: 3 }, { a: 2, b: 1, expected: 3 }, ])('describe object add($a, $b)', ({ a, b, expected }) => { test(`returns ${expected}`, () => { expect(a + b).toBe(expected) }) test(`returned value not be greater than ${expected}`, () => { expect(a + b).not.toBeGreaterThan(expected) }) test(`returned value not be less than ${expected}`, () => { expect(a + b).not.toBeLessThan(expected) }) })
describe.each([ { a: 1, b: 1, expected: 2 }, { a: 1, b: 2, expected: 3 }, { a: 2, b: 1, expected: 3 }, ])('describe object add($a, $b)', ({ a, b, expected }) => { test(`returns ${expected}`, () => { expect(a + b).toBe(expected) }) test(`returned value not be greater than ${expected}`, () => { expect(a + b).not.toBeGreaterThan(expected) }) test(`returned value not be less than ${expected}`, () => { expect(a + b).not.toBeLessThan(expected) }) })
Starting from Vitest 0.25.3, you can also use template string table.
- First row should be column names, separated by
|
; - One or more subsequent rows of data supplied as template literal expressions using
${value}
syntax.
tsdescribe.each` a | b | expected ${1} | ${1} | ${2} ${'a'} | ${'b'} | ${'ab'} ${[]} | ${'b'} | ${'b'} ${{}} | ${'b'} | ${'[object Object]b'} ${{ asd: 1 }} | ${'b'} | ${'[object Object]b'} `('describe template string add($a, $b)', ({ a, b, expected }) => { test(`returns ${expected}`, () => { expect(a + b).toBe(expected) }) })
describe.each` a | b | expected ${1} | ${1} | ${2} ${'a'} | ${'b'} | ${'ab'} ${[]} | ${'b'} | ${'b'} ${{}} | ${'b'} | ${'[object Object]b'} ${{ asd: 1 }} | ${'b'} | ${'[object Object]b'} `('describe template string add($a, $b)', ({ a, b, expected }) => { test(`returns ${expected}`, () => { expect(a + b).toBe(expected) }) })
- First row should be column names, separated by
WARNING
You cannot use this syntax, when using Vitest as type checker.
Setup and Teardown
These functions allow you to hook into the life cycle of tests to avoid repeating setup and teardown code. They apply to the current context: the file if they are used at the top-level or the current suite if they are inside a describe
block. These hooks are not called, when you are running Vitest as a type checker.
beforeEach
Type:
beforeEach(fn: () => Awaitable<void>, timeout?: number)
Register a callback to be called before each of the tests in the current context runs. If the function returns a promise, Vitest waits until the promise resolve before running the test.
Optionally, you can pass a timeout (in milliseconds) defining how long to wait before terminating. The default is 5 seconds.
tsimport { beforeEach } from 'vitest' beforeEach(async () => { // Clear mocks and add some testing data after before each test run await stopMocking() await addUser({ name: 'John' }) })
import { beforeEach } from 'vitest' beforeEach(async () => { // Clear mocks and add some testing data after before each test run await stopMocking() await addUser({ name: 'John' }) })
Here, the
beforeEach
ensures that user is added for each test.Since Vitest v0.10.0,
beforeEach
also accepts an optional cleanup function (equivalent toafterEach
).tsimport { beforeEach } from 'vitest' beforeEach(async () => { // called once before each test run await prepareSomething() // clean up function, called once after each test run return async () => { await resetSomething() } })
import { beforeEach } from 'vitest' beforeEach(async () => { // called once before each test run await prepareSomething() // clean up function, called once after each test run return async () => { await resetSomething() } })
afterEach
Type:
afterEach(fn: () => Awaitable<void>, timeout?: number)
Register a callback to be called after each one of the tests in the current context completes. If the function returns a promise, Vitest waits until the promise resolve before continuing.
Optionally, you can provide a timeout (in milliseconds) for specifying how long to wait before terminating. The default is 5 seconds.
tsimport { afterEach } from 'vitest' afterEach(async () => { await clearTestingData() // clear testing data after each test run })
import { afterEach } from 'vitest' afterEach(async () => { await clearTestingData() // clear testing data after each test run })
Here, the
afterEach
ensures that testing data is cleared after each test runs.
beforeAll
Type:
beforeAll(fn: () => Awaitable<void>, timeout?: number)
Register a callback to be called once before starting to run all tests in the current context. If the function returns a promise, Vitest waits until the promise resolve before running tests.
Optionally, you can provide a timeout (in milliseconds) for specifying how long to wait before terminating. The default is 5 seconds.
tsimport { beforeAll } from 'vitest' beforeAll(async () => { await startMocking() // called once before all tests run })
import { beforeAll } from 'vitest' beforeAll(async () => { await startMocking() // called once before all tests run })
Here the
beforeAll
ensures that the mock data is set up before tests run.Since Vitest v0.10.0,
beforeAll
also accepts an optional cleanup function (equivalent toafterAll
).tsimport { beforeAll } from 'vitest' beforeAll(async () => { // called once before all tests run await startMocking() // clean up function, called once after all tests run return async () => { await stopMocking() } })
import { beforeAll } from 'vitest' beforeAll(async () => { // called once before all tests run await startMocking() // clean up function, called once after all tests run return async () => { await stopMocking() } })
afterAll
Type:
afterAll(fn: () => Awaitable<void>, timeout?: number)
Register a callback to be called once after all tests have run in the current context. If the function returns a promise, Vitest waits until the promise resolve before continuing.
Optionally, you can provide a timeout (in milliseconds) for specifying how long to wait before terminating. The default is 5 seconds.
tsimport { afterAll } from 'vitest' afterAll(async () => { await stopMocking() // this method is called after all tests run })
import { afterAll } from 'vitest' afterAll(async () => { await stopMocking() // this method is called after all tests run })
Here the
afterAll
ensures thatstopMocking
method is called after all tests run.