テスト API リファレンス
以下の型は、下記の型シグネチャで使用されます。
type Awaitable<T> = T | PromiseLike<T>;
type TestFunction = () => Awaitable<void>;
interface TestOptions {
/**
* 実行時間が長すぎる場合にテストを失敗させます。
*/
timeout?: number;
/**
* テストが失敗した場合に、指定された回数だけテストを再試行します。
*
* @default 0
*/
retry?: number;
/**
* 毎回失敗した場合でも、同じテストを複数回繰り返します。
* "retry" オプションが設定されている場合、失敗時には各サイクルで設定された再試行回数だけ再試行します。
* ランダムな失敗をデバッグするのに役立ちます。
*
* @default 0
*/
repeats?: number;
}テスト関数が Promise を返す場合、ランナーは非同期処理の結果を収集するために、Promise が解決されるまで待機します。Promise が拒否された場合、テストは失敗します。
TIP
Jest では、TestFunction は (done: DoneCallback) => void 型にもなり得ます。この形式を使用する場合、done が呼び出されるまでテストは完了しません。async 関数を使用しても同じことができます。移行ガイドの Done Callback セクションを参照してください。
test
型:
(name: string | Function, fn: TestFunction, timeout?: number | TestOptions) => voidエイリアス:
ittestは、関連する期待値のセットを定義します。テスト名と、テスト対象の期待値を保持する関数を受け取ります。オプションで、タイムアウトまでの待機時間をミリ秒単位で指定できます。デフォルトは 5 秒で、testTimeout でグローバルに設定できます。
tsimport { expect, test } from 'vitest'; test('should work as expected', () => { expect(Math.sqrt(4)).toBe(2); });
test.extend
型:
<T extends Record<string, any>>(fixtures: Fixtures<T>): TestAPI<ExtraContext & T>エイリアス:
it.extendバージョン: Vitest 0.32.3
test.extendを使用して、カスタムフィクスチャでテストコンテキストを拡張します。これにより、新しいtestが返され、拡張可能にもなるため、必要に応じて拡張することで、より多くのフィクスチャを構成したり、既存のフィクスチャをオーバーライドしたりできます。詳細については、テストコンテキストの拡張を参照してください。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); });
test.skip
型:
(name: string | Function, fn: TestFunction, timeout?: number | TestOptions) => voidエイリアス:
it.skip特定のテストの実行をスキップしたいが、何らかの理由でコードを削除したくない場合は、
test.skipを使用して実行を回避できます。tsimport { assert, test } from 'vitest'; test.skip('skipped test', () => { // Test skipped, no error assert.equal(Math.sqrt(4), 3); });コンテキストの skip メソッドを動的に呼び出すことによって、テストをスキップすることもできます。
tsimport { assert, test } from 'vitest'; test('skipped test', context => { context.skip(); // Test skipped, no error assert.equal(Math.sqrt(4), 3); });
test.skipIf
型:
(condition: any) => Testエイリアス:
it.skipIf異なる環境でテストを複数回実行する場合、テストの一部が環境固有であることがあります。テストコードを
ifで囲む代わりに、条件が真と評価される場合は常にtest.skipIfを使用してテストをスキップできます。tsimport { assert, test } from 'vitest'; const isDev = process.env.NODE_ENV === 'development'; test.skipIf(isDev)('prod only test', () => { // このテストは production 環境でのみ実行されます });
WARNING
Vitest を 型チェッカーとして使用している場合、この構文は使用できません。
test.runIf
型:
(condition: any) => Testエイリアス:
it.runIftest.skipIf の反対です。
tsimport { assert, test } from 'vitest'; const isDev = process.env.NODE_ENV === 'development'; test.runIf(isDev)('dev only test', () => { // このテストは development 環境でのみ実行されます });
WARNING
Vitest を 型チェッカーとして使用している場合、この構文は使用できません。
test.only
型:
(name: string | Function, fn: TestFunction, timeout?: number) => voidエイリアス:
it.onlytest.onlyを使用して、特定のスイートで特定のテストのみを実行します。これはデバッグに役立ちます。オプションで、タイムアウトまでの待機時間をミリ秒単位で指定できます。デフォルトは 5 秒で、testTimeout でグローバルに設定できます。
tsimport { assert, test } from 'vitest'; test.only('test', () => { // このテスト(および only が付いた他のテスト)のみが実行されます assert.equal(Math.sqrt(4), 2); });出力が煩雑になるため、テストスイート全体から他のすべてのテストを無視して、特定のファイル内の
onlyテストを実行すると非常に便利な場合があります。これを行うには、対象のテストを含む特定のファイルで
vitestを実行します。# vitest interesting.test.ts
test.concurrent
型:
(name: string | Function, fn: TestFunction, timeout?: number) => voidエイリアス:
it.concurrenttest.concurrentは、複数のテストを並行して実行するようにマークします。テスト名、テストを含む非同期関数、およびオプションのタイムアウト(ミリ秒単位)を受け取ります。tsimport { describe, test } from 'vitest'; // concurrent が付いた 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は、並行テストで動作します。次のすべての組み合わせが有効です。tstest.concurrent(/* ... */); test.skip.concurrent(/* ... */); // または test.concurrent.skip(/* ... */) test.only.concurrent(/* ... */); // または test.concurrent.only(/* ... */) test.todo.concurrent(/* ... */); // または test.concurrent.todo(/* ... */)並行テストを実行する場合、スナップショットとアサーションは、正しいテストが検出されるように、ローカルの テストコンテキスト から
expectを使用する必要があります。tstest.concurrent('test 1', async ({ expect }) => { expect(foo).toMatchSnapshot(); }); test.concurrent('test 2', async ({ expect }) => { expect(foo).toMatchSnapshot(); });
WARNING
Vitest を 型チェッカーとして使用している場合、この構文は使用できません。
test.todo
型:
(name: string | Function) => voidエイリアス:
it.todotest.todoを使用して、後で実装されるテストのスタブを作成します。テストのレポートに項目が表示されるため、実装する必要があるテストの数がわかります。ts// このテストのエントリがレポートに表示されます test.todo('unimplemented test');
test.fails
型:
(name: string | Function, fn: TestFunction, timeout?: number) => voidエイリアス:
it.failstest.failsを使用して、アサーションが意図的に失敗することを示します。tsimport { expect, test } from 'vitest'; function myAsyncFunc() { return new Promise(resolve => resolve(1)); } test.fails('fail test', async () => { await expect(myAsyncFunc()).rejects.toBe(1); });
WARNING
Vitest を 型チェッカーとして使用している場合、この構文は使用できません。
test.each
型:
(cases: ReadonlyArray<T>, ...args: any[]) => voidエイリアス:
it.each異なる変数で同じテストを実行する必要がある場合は、
test.eachを使用します。 テスト関数パラメータの順序で、テスト名に printf 形式の書式でパラメータを挿入できます。%s: string%d: number%i: integer%f: floating point value%j: json%o: object%#: テストケースのインデックス%%: 単一のパーセント記号 ('%')
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オブジェクトを引数として使用している場合は、
$プレフィックスを使用してオブジェクトプロパティにアクセスすることもできます。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オブジェクトを引数として使用している場合は、
.を使用してオブジェクト属性にアクセスすることもできます。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) -> 3bVitest 0.25.3 以降では、テンプレートリテラルの表形式も使用できます。
- 最初の行は、
|で区切られた列名である必要があります。 - 1 つ以上の後続のデータ行は、
${value}構文を使用してテンプレートリテラル式として提供されます。
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); });TestContextにアクセスする場合は、単一のテストでdescribe.eachを使用します。
TIP
Vitest は、chai format メソッドで $values を処理します。値が過度に切り捨てられる場合は、構成ファイルで chaiConfig.truncateThreshold を増やすことができます。
WARNING
Vitest を 型チェッカーとして使用している場合、この構文は使用できません。
bench
- 型:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
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;
/**
* ベンチマークを中止するための AbortSignal。
*/
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
// テストの整理
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
// ベンチマークの整理
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) {
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
型:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void特定の
describeブロックの実行をスキップするには、スイート内でdescribe.skipを使用します。tsimport { assert, describe, test } from 'vitest'; describe.skip('skipped suite', () => { test('sqrt', () => { // スイートはスキップされるため、エラーは発生しません assert.equal(Math.sqrt(4), 3); }); });
describe.skipIf
型:
(condition: any) => void同じスイートを異なる環境で複数回実行する場合、一部のスイートが特定の環境に依存することがあります。スイートを
if文で囲む代わりに、条件が truthy の場合にスイートをスキップするには、describe.skipIfを使用します。tsimport { describe, test } from 'vitest'; const isDev = process.env.NODE_ENV === 'development'; describe.skipIf(isDev)('prod only test', () => { // このテストは本番環境でのみ実行されます });
WARNING
Vitest を 型チェッカーとして使用している場合、この構文は使用できません。
describe.only
型:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void特定のスイートのみを実行するには、
describe.onlyを使用します。ts// このスイート(および only でマークされた他のスイート)のみが実行されます describe.only('suite', () => { test('sqrt', () => { assert.equal(Math.sqrt(4), 3); }); }); describe('other suite', () => { // ... はスキップされます });テストスイート全体から他のテストを無視して、特定のファイル内の
onlyテストのみを実行すると、出力が整理されて非常に便利です。これを行うには、対象のテストを含む特定のファイルに対して
vitestを実行します。# vitest interesting.test.ts
describe.concurrent
型:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => voiddescribe.concurrentをスイート内で使用すると、すべてのテストが並行実行としてマークされます。ts// このスイート内のすべてのテストは並行して実行されます describe.concurrent('suite', () => { test('concurrent test 1', async () => { /* ... */ }); test('concurrent test 2', async () => { /* ... */ }); test.concurrent('concurrent test 3', async () => { /* ... */ }); });.skip、.only、および.todoは、並行スイートでも動作します。次のすべての組み合わせが有効です。tsdescribe.concurrent(/* ... */); describe.skip.concurrent(/* ... */); // または describe.concurrent.skip(/* ... */) describe.only.concurrent(/* ... */); // または describe.concurrent.only(/* ... */) describe.todo.concurrent(/* ... */); // または 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();
});
});WARNING
Vitest を 型チェッカーとして使用している場合、この構文は使用できません。
describe.sequential
型:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => voiddescribe.sequentialをスイート内で使用すると、すべてのテストが逐次実行としてマークされます。これは、describe.concurrent内、または--sequence.concurrentコマンドオプションを使用する際に、特定のテストを逐次実行したい場合に役立ちます。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.shuffle
型:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => voidVitest では、CLI フラグ
--sequence.shuffleまたは構成オプションsequence.shuffleを使用して、すべてのテストをランダムな順序で実行できます。テストスイートの一部のみをランダムな順序で実行したい場合は、このフラグで対象のスイートをマークします。tsdescribe.shuffle('suite', () => { test('random test 1', async () => { /* ... */ }); test('random test 2', async () => { /* ... */ }); test('random test 3', async () => { /* ... */ }); }); // 順序は、構成の sequence.seed オプションに依存します(デフォルトでは Date.now())
.skip、.only、および .todo は、ランダムスイートでも動作します。
WARNING
Vitest を 型チェッカーとして使用している場合、この構文は使用できません。
describe.todo
型:
(name: string | Function) => voiddescribe.todoは、後で実装するスイートのプレースホルダーを作成する際に使用します。レポートには、実装が必要なテストの数が表示されます。ts// このスイートのエントリがレポートに表示されます describe.todo('unimplemented suite');
describe.each
型:
(cases: ReadonlyArray<T>, ...args: any[]): (name: string | Function, fn: (...args: T[]) => void, options?: number | TestOptions) => void同じデータに依存する複数のテストがある場合は、
describe.eachを使用します。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); }); });Vitest 0.25.3 以降では、テンプレート文字列テーブルも使用できます。
- 最初の行は、
|で区切られた列名である必要があります。 - 1 つ以上の後続のデータ行は、
${value}構文を使用してテンプレートリテラル式として記述します。
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); }); });- 最初の行は、
WARNING
Vitest を 型チェッカーとして使用している場合、この構文は使用できません。
セットアップとティアダウン
これらの関数を使用すると、テストのライフサイクルにフックし、セットアップ/ティアダウンコードの繰り返しを避けることができます。これらの関数は現在のコンテキスト(ファイル先頭で使用されている場合はファイル全体、describe ブロック内にある場合はそのスイート)に適用されます。Vitest を型チェッカーとして実行している場合、これらのフックは実行されません。
beforeEach
型:
beforeEach(fn: () => Awaitable<void>, timeout?: number)現在のコンテキストで実行される各テストの前に呼び出されるコールバック関数を登録します。関数が Promise を返す場合、Vitest はテスト実行前に Promise が解決されるのを待ちます。
タイムアウト(ミリ秒)を渡すことで、タイムアウトまでの待機時間を設定できます。デフォルトは 5 秒です。
tsimport { beforeEach } from 'vitest'; beforeEach(async () => { // 各テストの実行前にモックをクリアし、テストデータを追加します await stopMocking(); await addUser({ name: 'John' }); });この例では、
beforeEachによって各テストの実行前にユーザーが追加されることが保証されます。Vitest v0.10.0 以降、
beforeEachはオプションのクリーンアップ関数(afterEachと同等)も受け入れます。tsimport { beforeEach } from 'vitest'; beforeEach(async () => { // 各テストの実行前に一度呼び出されます await prepareSomething(); // クリーンアップ関数。各テストの実行後に呼び出されます return async () => { await resetSomething(); }; });
afterEach
型:
afterEach(fn: () => Awaitable<void>, timeout?: number)現在のコンテキストで実行される各テストの完了後に呼び出されるコールバック関数を登録します。関数が Promise を返す場合、Vitest は処理を続行する前に Promise が解決されるのを待ちます。
オプションで、タイムアウトするまでの待機時間を指定するためのタイムアウト(ミリ秒単位)を提供できます。デフォルトは 5 秒です。
tsimport { afterEach } from 'vitest'; afterEach(async () => { await clearTestingData(); // 各テストの実行後にテストデータをクリアします });この例では、
afterEachは、各テストの実行後にテストデータがクリアされるようにします。
beforeAll
型:
beforeAll(fn: () => Awaitable<void>, timeout?: number)現在のコンテキストで、すべてのテストの実行を開始する前に一度だけ呼び出されるコールバック関数を登録します。関数が Promise を返す場合、Vitest はテスト実行前に Promise が解決されるのを待ちます。
オプションで、タイムアウトするまでの待機時間を指定するためのタイムアウト(ミリ秒単位)を提供できます。デフォルトは 5 秒です。
tsimport { beforeAll } from 'vitest'; beforeAll(async () => { await startMocking(); // すべてのテストの実行前に一度呼び出されます });この例では、
beforeAllは、テストの実行前にモックデータが設定されるようにします。Vitest v0.10.0 以降、
beforeAllはオプションのクリーンアップ関数(afterAllと同等)も受け入れます。tsimport { beforeAll } from 'vitest'; beforeAll(async () => { // すべてのテストの実行前に一度呼び出されます await startMocking(); // クリーンアップ関数。すべてのテストの実行後に一度呼び出されます return async () => { await stopMocking(); }; });
afterAll
型:
afterAll(fn: () => Awaitable<void>, timeout?: number)現在のコンテキストで、すべてのテストが実行された後に一度だけ呼び出されるコールバック関数を登録します。関数が Promise を返す場合、Vitest は処理を続行する前に Promise が解決されるのを待ちます。
オプションで、タイムアウトするまでの待機時間を指定するためのタイムアウト(ミリ秒単位)を提供できます。デフォルトは 5 秒です。
tsimport { afterAll } from 'vitest'; afterAll(async () => { await stopMocking(); // このメソッドは、すべてのテストの実行後に呼び出されます });この例では、
afterAllによって、stopMockingメソッドがすべてのテストの実行後に呼び出されることが保証されます。