【Vitest】公式ドキュメント日本語訳(API Reference*随時更新中)
Test API Reference
以下の型シグネチャでは次の型が使用されています。
type Awaitable<T> = T | PromiseLike<T>
type TestFunction = () => Awaitable<void>
interface TestOptions {
/**
* 実行に時間がかかりすぎるとテストは失敗します
*/
timeout?: number
/**
* 失敗した場合は、指定された回数だけテストを再試行します
*
* @default 0
*/
retry?: number
/**
* 毎回失敗しても、同じテストを複数回繰り返します。
* 「再試行」オプションがあり、失敗した場合は、各サイクルですべての再試行を使用します。
* ランダムな失敗をデバッグするのに役立ちます
*
* @default 0
*/
repeats?: number
}
Vitest 1.3.0 では、最後のパラメータとしてオプションを使用することは推奨されていません。この構文が削除される 2.0.0 までは、非推奨メッセージが表示されます。オプションを渡す必要がある場合は、テスト関数の 2 番目の引数を使用します。
import { test } from 'vitest'
× test('flaky test', () => {}, { retry: 3 })
◯ test('flaky test', { retry: 3 }, () => {})
テスト関数が Promise を返すと、ランナーはそれが解決されるまで待機し、非同期の期待値を収集します。Promise が拒否されると、テストは失敗します。
*Jest では、TestFunction
は(done: DoneCallback) => void
型になることもできます。この形式を使用すると、done
が呼び出されるまでテストは完了しません。非同期関数を使用して同じことを実現できます。移行ガイドのDone Callback
セクションを参照してください。
Vitest1.3.0以降、ほとんどのオプションはドット構文とオブジェクト構文の両方をサポートしており、好きなスタイルを使用できます。
ドット構文
import { test } from 'vitest'
test.skip('skipped test', () => {
// some logic that fails right now
})
オブジェクト構文
import { test } from 'vitest'
test('skipped test', { skip: true }, () => {
// some logic that fails right now
})
test
- エイリアス:
it
test
は、関連する期待値のセットを定義します。テスト名と、テストする期待値を保持する関数を受け取ります。
オプションで、終了するまでの待機時間を指定するためにタイムアウト (ミリ秒単位) を指定できます。デフォルトは 5 秒で、testTimeout を使用してグローバルに設定できます。
import { expect, test } from 'vitest'
test('should work as expected', () => {
expect(Math.sqrt(4)).toBe(2)
})
test.extend (0.32.3以降)
- エイリアス:
it.extend
test.extend
を使用して、決まった処理でテスト内容を拡張します。これにより新しいテストが返されます。拡張可能なテストなので、さらに処理を作成したり、既存の処理を上書きしたりできます。詳細については、「テストコンテキストの拡張」を参照してください。
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
- エイリアス:
it.skip
特定のテストの実行をスキップしたいけれど、コードを削除したくない場合は、test.skip
で実行を回避できます。
import { assert, test } from 'vitest'
test.skip('skipped test', () => {
// Test skipped, no error
assert.equal(Math.sqrt(4), 3)
})
コンテキスト上でskip
を動的に呼び出すことで、テストをスキップすることもできます。
test.skipIf
- エイリアス:
it.skipIf
場合によっては、異なる環境でテストを複数回実行することがあり、一部のテストは環境固有である可能性があります。テストコードをif
でラップする代わりに、条件がtrue
の場合はtest.skipIf
でテストをスキップできます。
*Vitest を型チェッカーとして使用する場合、この構文は使用できません。
import { assert, test } from 'vitest'
const isDev = process.env.NODE_ENV === 'development'
test.skipIf(isDev)('prod only test', () => {
// 本番環境でのみ実行される
})
test.runIf
- エイリアス:
it.runIf
test.skipIfの反対
*Vitest を型チェッカーとして使用する場合、この構文は使用できません。
import { assert, test } from 'vitest'
const isDev = process.env.NODE_ENV === 'development'
test.runIf(isDev)('dev only test', () => {
// 開発環境でのみ実行される
})
test.only
- エイリアス:
it.only
test.only
を使用すると、特定のスイート内の特定のテストのみを実行できます。これはデバッグ時に便利です。
オプションで、終了するまでの待機時間を指定するためにタイムアウト(ミリ秒単位)を指定できます。デフォルトは5秒で、testTimeout
を使用してグローバルに設定できます。
import { assert, test } from 'vitest'
test.only('test', () => {
// このテスト(およびマークの付いた他のテスト)のみが実行されます
assert.equal(Math.sqrt(4), 2)
})
場合によっては、出力を汚染するテストスイート全体の他のすべてのテストを無視して、特定のファイル内のテストのみを実行すると非常に便利です。
これを行うには、問題のテストを含む特定のファイルでvitest
を実行します。
# vitest interesting.test.ts
test.concurrent
- エイリアス:
it.concurrent
test.concurrent
は、連続して実行されるテストをマークします。テスト名、収集するテストを含む非同期関数、およびオプションのタイムアウト (ミリ秒単位) を受け取ります。
import { describe, test } from 'vitest'
// 同時実行とマークされた2つのテストは並行して実行されます。
describe('suite', () => {
test('serial test', async () => { /* ... */ })
test.concurrent('concurrent test 1', async () => { /* ... */ })
test.concurrent('concurrent test 2', async () => { /* ... */ })
})
test.skip
、test.only
、test.todo
は同時テストで機能します。次の組み合わせはすべて有効です。
test.concurrent(/* ... */)
test.skip.concurrent(/* ... */) // or test.concurrent.skip(/* ... */)
test.only.concurrent(/* ... */) // or test.concurrent.only(/* ... */)
test.todo.concurrent(/* ... */) // or test.concurrent.todo(/* ... */)
同時テストを実行する場合、スナップショットとアサーションは、適切なテストが検出されるように、ローカルのテストコンテキストからのexpect
を使用する必要があります。
test.concurrent('test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot()
})
test.concurrent('test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot()
})
*Vitest を型チェッカーとして使用する場合、この構文は使用できません。
test.sequential
- エイリアス:
it.sequential
test.sequential
はテストを一連のものとしてマークします。これは、describe.concurrent
内または--sequence.concurrent
オプションを使用してテストを順番に実行する場合に役立ちます。
// with config option { sequence: { concurrent: true } }
test('concurrent test 1', async () => { /* ... */ })
test('concurrent test 2', async () => { /* ... */ })
test.sequential('sequential test 1', async () => { /* ... */ })
test.sequential('sequential test 2', async () => { /* ... */ })
// within concurrent suite
describe.concurrent('suite', () => {
test('concurrent test 1', async () => { /* ... */ })
test('concurrent test 2', async () => { /* ... */ })
test.sequential('sequential test 1', async () => { /* ... */ })
test.sequential('sequential test 2', async () => { /* ... */ })
})
test.todo
- エイリアス:
it.todo
test.todo
を使用して、後で実装するテストをスタブします。テストのエントリがレポートに表示されるので、まだ実装する必要があるテストの数を確認できます。
// テストのレポートにエントリが表示されます
test.todo('unimplemented test')
test.fails
- エイリアス:
it.fails
アサーションが明示的に失敗することを示す際に使用します。
*Vitest を型チェッカーとして使用する場合、この構文は使用できません。
import { expect, test } from 'vitest'
function myAsyncFunc() {
return new Promise(resolve => resolve(1))
}
test.fails('fail test', async () => {
await expect(myAsyncFunc()).rejects.toBe(1)
})
test.each
- エイリアス:
it.each
異なる変数を使用して同じテストを実行する場合に使用します。テスト関数のパラメータの順序で、テスト名にprintf
形式のパラメータを挿入できます。
-
%s
: string -
%d
: number -
%i
: integer -
%f
: floating point value -
%j
: json -
%o
: object -
%#
: index of the test case -
%%
: single percent sign ('%')
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
オブジェクトを引数として使用している場合は、$
プレフィックスを使用してオブジェクトのプロパティにアクセスすることもできます。
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
オブジェクトを引数として使用している場合は、.
を使用してオブジェクト属性にアクセスすることもできます。
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
Vitest 0.25.3以降では、テンプレート文字列のテーブルも使用できます。
- 最初の行は列名で、
|
で区切る - 1行以上のデータは、
${value}
構文を使用してテンプレートリテラルで書く
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)
})
TestContext
にアクセスする場合は、単一のテストでdescribe.each
を使用します。
- Vitestは、Chaiフォーマット方式で
$values
を処理します。値が切り捨てられすぎている場合は、設定ファイルでchaiConfig.truncateThreshold
を増やすことができます。 - Vitest を型チェッカーとして使用する場合、この構文は使用できません。
bench
- タイプ:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
bench
はベンチマークを定義します。Vitestでは、ベンチマークは一連の操作を定義する関数です。Vitestはこの関数を複数回実行して、さまざまなパフォーマンス結果を表示します。
Vitestは内部でtinybench
ライブラリを使用し、3番目の引数として使用できるすべてのオプションを継承します。
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 {
/**
* ベンチマークタスクの実行に必要な時間(ミリ秒)
* @default 500
*/
time?: number
/**
* 時間オプションが終了した場合にタスクを実行する回数
* @default 10
*/
iterations?: number
/**
* 現在のタイムスタンプをミリ秒単位で取得する関数
*/
now?: () => number
/**
* ベンチマークを中止するための中止シグナル
*/
signal?: AbortSignal
/**
* ウォームアップ時間(ミリ秒)
* @default 100ms
*/
warmupTime?: number
/**
* ウォームアップ反復
* @default 5
*/
warmupIterations?: number
/**
* 各ベンチマークタスク(サイクル)の前に実行するセットアップ関数
*/
setup?: Hook
/**
* 各ベンチマークタスク(サイクル)後に実行されるティアダウン関数
*/
teardown?: Hook
}
bench.skip
- タイプ:
(name: string | Function、fn: BenchFunction、options?: BenchOptions) => void
bench.skip
構文を使用して、特定のベンチマークの実行をスキップできます。
import { bench } from 'vitest'
bench.skip('normal sorting', () => {
const x = [1, 5, 4, 2, 3]
x.sort((a, b) => {
return a - b
})
})
bench.only
- タイプ:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
特定のスイート内の特定のベンチマークのみを実行するには、bench.only
を使用します。これはデバッグ時に便利です。
import { bench } from 'vitest'
bench.only('normal sorting', () => {
const x = [1, 5, 4, 2, 3]
x.sort((a, b) => {
return a - b
})
})
bench.todo
- タイプ:
(name: string | Function) => void
bench.todo
を使用して、後で実装するベンチマークをスタブします。
import { bench } from 'vitest'
bench.todo('unimplemented test')
describe
ファイルの最上位レベルでtest
またはbench
を使用すると、それらは暗黙的な一揃いの部品として収集されます。describe
を使用すると、関連するテストまたはベンチマークとその他のネストされた一組として、現在のコンテキストで新しいスイートを定義できます。スイートを使用すると、テストとベンチマークを整理して、レポートをより明確にすることができます。
// 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
})
})
})
テストやベンチマークの階層がある場合は、describe ブロックをネストすることもできます。
import { describe, expect, test } from 'vitest'
function numberToCurrency(value: number | string) {
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
- エイリアス:
suite.skip
特定のdescribe
ブロックの実行を回避するには、スイート内でdescribe.skip
を使用します。
import { assert, describe, test } from 'vitest'
describe.skip('skipped suite', () => {
test('sqrt', () => {
// スイートはスキップされましたが、エラーはない
assert.equal(Math.sqrt(4), 3)
})
})
describe.skipIf
- エイリアス:
suite.skipIf
場合によっては、異なる環境でスイートを複数回実行することがあり、スイートの一部は環境固有である可能性があります。スイートをif
でラップする代わりに、describe.skipIf
を使用して、条件が真であるたびにスイートをスキップできます。
*Vitest を型チェッカーとして使用する場合、この構文は使用できません。
import { describe, test } from 'vitest'
const isDev = process.env.NODE_ENV === 'development'
describe.skipIf(isDev)('prod only test suite', () => {
// 本番環境でのみ実行される
})
describe.runIf
- エイリアス:
suite.runIf
describe.skipIf
の反対
*Vitest を型チェッカーとして使用する場合、この構文は使用できません。
import { assert, describe, test } from 'vitest'
const isDev = process.env.NODE_ENV === 'development'
describe.runIf(isDev)('dev only test suite', () => {
// 開発環境でのみ実行される
})
describe.only
- Type:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
特定のスイートのみを実行するには、describe.only を使用します。
// このスイート(およびマークの付いた他のスイート)のみが実行されます
describe.only('suite', () => {
test('sqrt', () => {
assert.equal(Math.sqrt(4), 3)
})
})
describe('other suite', () => {
// スキップされる
})
場合によっては、出力を汚染するテストスイート全体の他のすべてのテストを無視して、特定のファイル内のテストのみを実行すると非常に便利です。
これを行うには、問題のテストを含む特定のファイルでvitest
を実行します。
# vitest interesting.test.ts
describe.concurrent
- エイリアス:
suite.concurrent
スイート内のdescribe.concurrent
は、すべてのテストを同時実行としてマークします。
// このスイート内のテストは全て、並行して実行される
describe.concurrent('suite', () => {
test('concurrent test 1', async () => { /* ... */ })
test('concurrent test 2', async () => { /* ... */ })
test.concurrent('concurrent test 3', async () => { /* ... */ })
})
.skip
、.only
、および .todo
は同時実行スイートで動作します。次の組み合わせはすべて有効です。
describe.concurrent(/* ... */)
describe.skip.concurrent(/* ... */) // or describe.concurrent.skip(/* ... */)
describe.only.concurrent(/* ... */) // or describe.concurrent.only(/* ... */)
describe.todo.concurrent(/* ... */) // or describe.concurrent.todo(/* ... */)
同時テストを実行する場合、スナップショットとアサーションは、適切なテストが検出されるように、ローカルのテストコンテキストからのexpect
を使用する必要があります。
describe.concurrent('suite', () => {
test('concurrent test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot()
})
test('concurrent test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot()
})
})
*Vitest を型チェッカーとして使用する場合、この構文は使用できません。
describe.sequential
- エイリアス:
suite.sequential
スイート内のdescribe.sequential
は、すべてのテストを連続するものとしてマークします。これは、describe.concurrent
内または--sequence.concurrent
オプションを使用してテストを順番に実行する場合に役立ちます。
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
- エイリアス:
suite.shuffle
Vitest は、CLI フラグ--sequence.shuffle
または構成オプションのsequence.shuffle
を使用してすべてのテストをランダムな順序で実行する方法を提供しますが、テストスイートの一部のみをランダムな順序でテストを実行する場合は、このフラグでマークできます。
describe.shuffle('suite', () => {
test('random test 1', async () => { /* ... */ })
test('random test 2', async () => { /* ... */ })
test('random test 3', async () => { /* ... */ })
})
// 順序は設定のsequence.seedオプションに依存する(デフォルトではDate.now())。
describe.todo
- エイリアス:
suite.todo
後で実装するスタブスイートを作成するには、describe.todo
を使用します。テストのエントリがレポートに表示されるので、まだ実装する必要があるテストの数を把握できます。
// スイートのレポートにエントリが表示されます
describe.todo('unimplemented suite')
describe.each
- エイリアス:
suite.each
同じデータに依存するテストが複数ある場合は、describe.each
を使用します。
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)
})
})
Vitest 0.25.3 以降では、テンプレート文字列テーブルも使用できます。
- 最初の行は列名で、
|
で区切る - 1行以上のデータは、
${value}
構文を使用してテンプレートリテラルで書く
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)
})
})
- Vitest を型チェッカーとして使用する場合、この構文は使用できません。
Setup と Teardown
これらの関数を使用すると、テストのライフサイクルにフックして、セットアップとティアダウンのコードの繰り返しを回避できます。これらは現在のコンテキストに適用されます。トップレベルで使用される場合はファイル、describe
ブロック内で使用される場合は現在のスイートに適用されます。Vitest を型チェッカーとして実行している場合は、これらのフックは呼び出されません。
beforeEach
- タイプ:
beforeEach(fn: () => Awaitable<void>, timeout?: number)
現在のコンテキストで各テストが実行される前に呼び出されるコールバックを登録します。関数がプロミスを返す場合、Vitestはプロミスが解決されるまで待機してからテストを実行します。
オプションで、終了するまでの待機時間を定義するタイムアウト (ミリ秒単位) を渡すことができます。デフォルトは5秒です。
import { beforeEach } from 'vitest'
beforeEach(async () => {
// 各テストの実行前にモックをクリアし、テストデータを追加
await stopMocking()
await addUser({ name: 'John' })
})
ここで、beforeEach
は各テストにユーザーが追加されることを保証します。
Vitest v0.10.0以降、beforeEach
はオプションのクリーンアップ関数(afterEach
と同等) も受け入れます。
import { beforeEach } from 'vitest'
beforeEach(async () => {
// 各テスト実行前に1回呼び出される
await prepareSomething()
// 各テスト実行後に一度呼び出されるクリーンアップ関数
return async () => {
await resetSomething()
}
})
afterEach
- タイプ:
afterEach(fn: () => Awaitable<void>, timeout?: number)
現在のコンテキスト内の各テストが完了した後に呼び出されるコールバックを登録します。関数がプロミスを返す場合、Vitestはプロミスが解決されるまで待機してから続行します。
オプションで、終了するまでの待機時間を指定するためのタイムアウト (ミリ秒単位) を指定できます。デフォルトは5秒です。
import { afterEach } from 'vitest'
afterEach(async () => {
await clearTestingData() // clear testing data after each test run
})
ここで、afterEach
は、各テストの実行後にテストデータがクリアされることを保証します。
- Vitest 1.3.0 では
onTestFinished
フックが追加されました。テスト実行中にこれを呼び出すと、テストの実行が完了した後の状態をクリーンアップできます。
beforeAll
- タイプ:
beforeAll(fn: () => Awaitable<void>, timeout?: number)
現在のコンテキストですべてのテストの実行を開始する前に1回呼び出されるコールバックを登録します。関数がプロミスを返す場合、Vitest はプロミスが解決されるまで待機してからテストを実行します。
オプションで、終了するまでの待機時間を指定するためのタイムアウト (ミリ秒単位) を指定できます。デフォルトは 5 秒です。
import { beforeAll } from 'vitest'
beforeAll(async () => {
await startMocking() // すべてのテストが実行される前に一度呼び出される
})
ここで、beforeAll
は、テストの実行前にモックデータがセットアップされることを保証します。
Vitest v0.10.0以降、beforeAll
はオプションのクリーンアップ関数 (afterAll
と同等) も受け入れます。
import { beforeAll } from 'vitest'
beforeAll(async () => {
// すべてのテストが実行される前に一度呼び出される
await startMocking()
// すべてのテストの実行後に一度呼び出されるクリーンアップ関数
return async () => {
await stopMocking()
}
})
afterAll
- タイプ:
afterAll(fn: () => Awaitable<void>, timeout?: number)
現在のコンテキストですべてのテストが実行された後に1回呼び出されるコールバックを登録します。関数がプロミスを返す場合、Vitestはプロミスが解決されるまで待機してから続行します。
オプションで、終了するまでの待機時間を指定するためのタイムアウト (ミリ秒単位) を指定できます。デフォルトは5秒です。
import { afterAll } from 'vitest'
afterAll(async () => {
await stopMocking() // すべてのテストの実行後に呼び出される
})
ここで、afterAll
は、すべてのテストの実行後にstopMocking
メソッドが呼び出されることを保証します。
Discussion