テスト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セクションを参照してください。
関数にプロパティをチェーンしてオプションを定義できます。
import { test } from 'vitest';
test.skip('スキップされたテスト', () => {
// some logic that fails right now
});
test.concurrent.skip('スキップされた並行テスト', () => {
// some logic that fails right now
});ただし、代わりにオブジェクトを2番目の引数として提供することも可能です。
import { test } from 'vitest';
test('スキップされたテスト', { skip: true }, () => {
// some logic that fails right now
});
test('スキップされた並行テスト', { skip: true, concurrent: true }, () => {
// some logic that fails right now
});どちらも全く同じように機能します。どちらを選ぶかは純粋にスタイルの問題です。
タイムアウトを最後の引数として指定する場合、オプションは使用できなくなる点に注意してください。
import { test } from 'vitest';
// ✅ これは動作します
test.skip('重いテスト', () => {
// ...
}, 10_000);
// ❌ これは動作しません
test(
'重いテスト',
{ skip: true },
() => {
// ...
},
10_000
);ただし、オブジェクト内にタイムアウトを指定することも可能です。
import { test } from 'vitest';
// ✅ これは動作します
test('重いテスト', { skip: true, timeout: 10_000 }, () => {
// ...
});test
- エイリアス:
it
test は関連する期待値のセットを定義します。テスト名と、テスト対象の期待値を含む関数を受け取ります。
オプションとして、終了するまでの待機時間をミリ秒単位で指定するタイムアウトを提供できます。デフォルトは5秒で、testTimeoutでグローバルに設定できます。
import { expect, test } from 'vitest';
test('期待通りに動作するはずです', () => {
expect(Math.sqrt(4)).toBe(2);
});test.extend
- エイリアス:
it.extend
test.extend を使用して、カスタムフィクスチャでテストコンテキストを拡張します。これにより新しい test が返され、これも拡張可能であるため、必要に応じてさらにフィクスチャを構成したり、既存のものを上書きしたりできます。詳細については、テストコンテキストの拡張を参照してください。
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('スキップされたテスト', () => {
// Test skipped, no error
assert.equal(Math.sqrt(4), 3);
});テストのコンテキストで skip を動的に呼び出すことでも、テストをスキップできます。
import { assert, test } from 'vitest';
test('スキップされたテスト', context => {
context.skip();
// Test skipped, no error
assert.equal(Math.sqrt(4), 3);
});Vitest 3.1以降、条件が不明な場合は、skip メソッドの最初の引数として指定できます。
import { assert, test } from 'vitest';
test('スキップされたテスト', context => {
context.skip(Math.random() < 0.5, 'optional message');
// Test skipped, no error
assert.equal(Math.sqrt(4), 3);
});test.skipIf
- エイリアス:
it.skipIf
場合によっては、異なる環境でテストを複数回実行することがあり、その一部は環境固有である可能性があります。テストコードを if で囲む代わりに、test.skipIf を使用して、条件が真と評価される場合にテストをスキップできます。
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.skipIf(isDev)('prod only test', () => {
// このテストは本番環境でのみ実行されます
});WARNING
Vitestを型チェッカーとして使用している場合、この構文は使用できません。
test.runIf
- エイリアス:
it.runIf
test.skipIfとは逆の機能です。
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.runIf(isDev)('dev only test', () => {
// このテストは開発環境でのみ実行されます
});WARNING
Vitestを型チェッカーとして使用している場合、この構文は使用できません。
test.only
- エイリアス:
it.only
特定のテストのみをスイートで実行したい場合は、test.only を使用します。これはデバッグ時に有用です。
オプションとして、終了するまでの待機時間をミリ秒単位で指定するタイムアウトを提供できます。デフォルトは5秒で、testTimeoutでグローバルに設定できます。
import { assert, test } from 'vitest';
test.only('test', () => {
// このテスト(およびonlyとマークされた他のテスト)のみが実行されます
assert.equal(Math.sqrt(4), 2);
});テストスイート全体から他のテストを無視し、出力の汚染を防ぐために、特定のファイル内の only テストのみを実行することが非常に有用な場合があります。
そのためには、対象のテストを含む特定のファイルで vitest を実行します。
# vitest interesting.test.tstest.concurrent
- エイリアス:
it.concurrent
test.concurrent は、連続するテストを並行して実行するよう指定します。テスト名、実行するテストを含む非同期関数、およびオプションのタイムアウト(ミリ秒単位)を受け取ります。
import { 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 は並行テストで機能します。以下のすべての組み合わせが有効です。
test.concurrent(/* ... */);
test.skip.concurrent(/* ... */); // または test.concurrent.skip(/* ... */)
test.only.concurrent(/* ... */); // または test.concurrent.only(/* ... */)
test.todo.concurrent(/* ... */); // または test.concurrent.todo(/* ... */)並行テストを実行する場合、スナップショットとアサーションは、適切なテストが認識されるように、ローカルのテストコンテキストから expect を使用する必要があります。
test.concurrent('test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test.concurrent('test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});WARNING
Vitestを型チェッカーとして使用している場合、この構文は使用できません。
test.sequential
- エイリアス:
it.sequential
test.sequential はテストをシーケンシャルとしてマークします。これは、describe.concurrent 内または --sequence.concurrent コマンドオプションを使用してテストを順次実行したい場合に有用です。
import { describe, test } from 'vitest';
// 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
アサーションが意図的に失敗することを示すには、test.fails を使用します。
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
Vitestを型チェッカーとして使用している場合、この構文は使用できません。
test.each
- エイリアス:
it.each
TIP
test.each はJestとの互換性のために提供されていますが、 VitestにはTestContextを統合する追加機能を持つtest.forも用意されています。
異なる変数で同じテストを実行する必要がある場合は、test.each を使用します。 テスト関数パラメータの順序に従って、テスト名にprintfフォーマットを使用してパラメータを挿入できます。
%s: 文字列%d: 数値%i: 整数%f: 浮動小数点値%j: JSON%o: オブジェクト%#: テストケースの0ベースインデックス%$: テストケースの1ベースインデックス%%: 単一のパーセント記号('%')
import { expect, test } from 'vitest';
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// 以下のように表示されます
// ✓ 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);
});
// 以下のように表示されます
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add($0, $1) -> $2', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// 以下のように表示されます
// ✓ 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);
});
// 以下のように表示されます
// ✓ add(1, b) -> 1b
// ✓ add(2, b) -> 2b
// ✓ add(3, b) -> 3bVitest 0.25.3以降、テンプレート文字列テーブルも使用できます。
- 最初の行は、
|で区切られた列名である必要があります。 - 1つ以上の後続の行は、
${value}構文を使用したテンプレートリテラル式としてデータを提供します。
import { expect, test } from 'vitest';
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);
});TIP
Vitestは $values をChaiの format メソッドで処理します。値が過度に切り詰められる場合は、設定ファイルでchaiConfig.truncateThresholdを増やすことができます。
WARNING
Vitestを型チェッカーとして使用している場合、この構文は使用できません。
test.for
- エイリアス:
it.for
TestContextを提供するためのtest.eachの代替です。
test.eachとの違いは、引数で配列がどのように提供されるかにあります。 test.forへの非配列引数(テンプレート文字列の使用を含む)は、test.eachと全く同じように動作します。
// each は配列を展開します
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// for は配列を展開しません(引数周りの角括弧に注目してください)
test.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => {
expect(a + b).toBe(expected);
});2番目の引数はTestContextであり、例えば並行スナップショットに利用できます。
test.concurrent.for([
[1, 1],
[1, 2],
[2, 1],
])('add(%i, %i)', ([a, b], { expect }) => {
expect(a + b).matchSnapshot();
});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;
/**
* timeオプションが終了した後もタスクを実行する回数
* @default 10
*/
iterations?: number;
/**
* 現在のタイムスタンプをミリ秒で取得する関数
*/
now?: () => number;
/**
* ベンチマークを中止するためのAbortSignal
*/
signal?: AbortSignal;
/**
* タスクが失敗した場合にエラーをスローする(trueの場合、イベントは機能しません)
*/
throws?: boolean;
/**
* ウォームアップ時間(ミリ秒)
* @default 100ms
*/
warmupTime?: number;
/**
* ウォームアップの繰り返し回数
* @default 5
*/
warmupIterations?: number;
/**
* 各ベンチマークタスク(サイクル)の前に実行されるセットアップ関数
*/
setup?: Hook;
/**
* 各ベンチマークタスク(サイクル)の後に実行されるティアダウン関数
*/
teardown?: Hook;
}テストケース実行後の出力構造は以下の通りです。
name hz min max mean p75 p99 p995 p999 rme samples
· normal sorting 6,526,368.12 0.0001 0.3638 0.0002 0.0002 0.0002 0.0002 0.0004 ±1.41% 652638export interface TaskResult {
/*
* タスクの実行中に発生した最後のエラー
*/
error?: unknown;
/**
* ベンチマークタスク(サイクル)の実行にかかった時間(ミリ秒)。
*/
totalTime: number;
/**
* サンプル内の最小値
*/
min: number;
/**
* サンプル内の最大値
*/
max: number;
/**
* 1秒あたりの操作数
*/
hz: number;
/**
* 各操作にかかる時間(ms)
*/
period: number;
/**
* 各タスクのイテレーション時間のサンプル(ミリ秒)
*/
samples: number[];
/**
* サンプルの平均値(母集団平均の推定値)
*/
mean: number;
/**
* サンプルの分散(母集団分散の推定値)
*/
variance: number;
/**
* サンプルの標準偏差(母集団標準偏差の推定値)
*/
sd: number;
/**
* 平均の標準誤差(別名、標本平均のサンプリング分布の標準偏差)
*/
sem: number;
/**
* 自由度
*/
df: number;
/**
* サンプルの臨界値
*/
critical: number;
/**
* 誤差範囲
*/
moe: number;
/**
* 相対誤差範囲
*/
rme: number;
/**
* 中央絶対偏差
*/
mad: number;
/**
* p50/中央値パーセンタイル
*/
p50: number;
/**
* p75パーセンタイル
*/
p75: number;
/**
* p99パーセンタイル
*/
p99: number;
/**
* p995パーセンタイル
*/
p995: number;
/**
* p999パーセンタイル
*/
p999: number;
}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 TypeError('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 を使用して、条件が真と評価される場合にスイートをスキップできます。
import { describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.skipIf(isDev)('prod only test suite', () => {
// このテストスイートは本番環境でのみ実行されます
});WARNING
Vitestを型チェッカーとして使用している場合、この構文は使用できません。
describe.runIf
- エイリアス:
suite.runIf
describe.skipIfとは逆の機能です。
import { assert, describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.runIf(isDev)('dev only test suite', () => {
// このテストスイートは開発環境でのみ実行されます
});WARNING
Vitestを型チェッカーとして使用している場合、この構文は使用できません。
describe.only
- 型:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
特定のスイートのみを実行するには、describe.only を使用します。
import { assert, describe, test } from 'vitest';
// このスイート(およびonlyとマークされた他のスイート)のみが実行されます
describe.only('suite', () => {
test('sqrt', () => {
assert.equal(Math.sqrt(4), 3);
});
});
describe('other suite', () => {
// ... スキップされます
});テストスイート全体から他のテストを無視し、出力の汚染を防ぐために、特定のファイル内の only テストのみを実行することが非常に有用な場合があります。
そのためには、対象のテストを含む特定のファイルで vitest を実行します。
# vitest interesting.test.tsdescribe.concurrent
- エイリアス:
suite.concurrent
describe.concurrent は、全ての内部スイートとテストを並行して実行します。
import { describe, test } from 'vitest';
// このスイート内の全てのスイートとテストは並行して実行されます
describe.concurrent('suite', () => {
test('concurrent test 1', async () => {
/* ... */
});
describe('concurrent suite 2', async () => {
test('concurrent test inner 1', async () => {
/* ... */
});
test('concurrent test inner 2', async () => {
/* ... */
});
});
test.concurrent('concurrent test 3', async () => {
/* ... */
});
});.skip、.only、および .todo は並行スイートで機能します。以下のすべての組み合わせが有効です。
describe.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
- エイリアス:
suite.sequential
スイートで describe.sequential を使用すると、全てのテストがシーケンシャルとしてマークされます。これは、describe.concurrent 内または --sequence.concurrent コマンドオプションを使用してテストを順次実行したい場合に有用です。
import { describe, test } from 'vitest';
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を介して全てのテストをランダムな順序で実行する方法を提供しますが、テストスイートの一部のみをランダムな順序で実行したい場合は、このフラグで指定できます。
import { describe, test } from 'vitest';
// または describe('suite', { shuffle: true }, ...)
describe.shuffle('suite', () => {
test('random test 1', async () => {
/* ... */
});
test('random test 2', async () => {
/* ... */
});
test('random test 3', async () => {
/* ... */
});
// shuffle は継承されます
describe('still random', () => {
test('random 4.1', async () => {
/* ... */
});
test('random 4.2', async () => {
/* ... */
});
});
// 内部で shuffle を無効にする
describe('not random', { shuffle: false }, () => {
test('in order 5.1', async () => {
/* ... */
});
test('in order 5.2', async () => {
/* ... */
});
});
});
// 順序は設定の sequence.seed オプションに依存します(デフォルトは Date.now()).skip、.only、および .todo はランダムスイートで機能します。
WARNING
Vitestを型チェッカーとして使用している場合、この構文は使用できません。
describe.todo
- エイリアス:
suite.todo
後で実装するスイートをスタブ化するには、describe.todo を使用します。このスイートのレポートに項目が表示されるため、まだ実装する必要があるテストの数がわかります。
// このスイートの項目がレポートに表示されます
describe.todo('unimplemented suite');describe.each
- エイリアス:
suite.each
TIP
describe.each はJestとの互換性のために提供されていますが、 Vitestには引数型を簡素化し、test.forと整合性のあるdescribe.forも用意されています。
同じデータに依存するテストが複数ある場合は、describe.each を使用します。
import { describe, expect, test } from 'vitest';
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}構文を使用したテンプレートリテラル式としてデータを提供します。
import { describe, expect, test } from 'vitest';
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);
});
});WARNING
Vitestを型チェッカーとして使用している場合、この構文は使用できません。
describe.for
- エイリアス:
suite.for
describe.eachとの違いは、引数で配列がどのように渡されるかにあります。 その他の非配列の場合(テンプレート文字列の使用を含む)は、全く同じように動作します。
// each は配列ケースを展開します
describe.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
test('test', () => {
expect(a + b).toBe(expected);
});
});
// for は配列ケースを展開しません
describe.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => {
test('test', () => {
expect(a + b).toBe(expected);
});
});セットアップとティアダウン
これらの関数を使用すると、テストのライフサイクルに介入し、セットアップとティアダウンのコードの繰り返しを避けることができます。これらは現在のコンテキストに適用されます。トップレベルで使用されている場合はファイルに、describe ブロック内にある場合は現在のスイートに適用されます。Vitestを型チェッカーとして実行している場合、これらのフックは呼び出されません。
beforeEach
- 型:
beforeEach(fn: () => Awaitable<void>, timeout?: number)
現在のコンテキスト内の各テストが実行される前に呼び出されるコールバックを登録します。 関数がPromiseを返す場合、Vitestはテストを実行する前にそのPromiseが解決されるまで待機します。
オプションとして、終了するまでの待機時間をミリ秒単位で定義するタイムアウトを渡すことができます。デフォルトは5秒です。
import { beforeEach } from 'vitest';
beforeEach(async () => {
// 各テスト実行前にモックをクリアし、テストデータを追加
await stopMocking();
await addUser({ name: 'John' });
});ここで、beforeEach は各テストでユーザーが追加されることを保証します。
beforeEach はオプションのクリーンアップ関数(afterEach と同等)も受け付けます。
import { beforeEach } from 'vitest';
beforeEach(async () => {
// 各テスト実行前に一度呼び出されます
await prepareSomething();
// クリーンアップ関数、各テスト実行後に一度呼び出されます
return async () => {
await resetSomething();
};
});afterEach
- 型:
afterEach(fn: () => Awaitable<void>, timeout?: number)
現在のコンテキスト内の各テストが完了した後に呼び出されるコールバックを登録します。 関数がPromiseを返す場合、Vitestは続行する前にそのPromiseが解決されるまで待機します。
オプションとして、終了するまでの待機時間を指定するためのタイムアウト(ミリ秒単位)を提供できます。デフォルトは5秒です。
import { afterEach } from 'vitest';
afterEach(async () => {
await clearTestingData(); // 各テスト実行後にテストデータをクリア
});ここで、afterEach は各テストの実行後にテストデータがクリアされることを保証します。
TIP
Vitest 1.3.0でonTestFinishedフックが追加されました。テスト実行中にこれを呼び出すことで、テストが終了した後に状態をクリーンアップできます。
beforeAll
- 型:
beforeAll(fn: () => Awaitable<void>, timeout?: number)
現在のコンテキスト内の全てのテストの実行を開始する前に一度呼び出されるコールバックを登録します。 関数がPromiseを返す場合、Vitestはテストを実行する前にそのPromiseが解決されるまで待機します。
オプションとして、終了するまでの待機時間を指定するためのタイムアウト(ミリ秒単位)を提供できます。デフォルトは5秒です。
import { beforeAll } from 'vitest';
beforeAll(async () => {
await startMocking(); // 全てのテスト実行前に一度呼び出されます
});ここで beforeAll は、テストが実行される前にモックデータがセットアップされることを保証します。
beforeAll はオプションのクリーンアップ関数(afterAll と同等)も受け入れます。
import { beforeAll } from 'vitest';
beforeAll(async () => {
// 全てのテスト実行前に一度呼び出されます
await startMocking();
// クリーンアップ関数、全てのテスト実行後に一度呼び出されます
return async () => {
await stopMocking();
};
});afterAll
- 型:
afterAll(fn: () => Awaitable<void>, timeout?: number)
現在のコンテキスト内の全てのテストが実行された後に一度呼び出されるコールバックを登録します。 関数がPromiseを返す場合、Vitestは続行する前にそのPromiseが解決されるまで待機します。
オプションとして、終了するまでの待機時間を指定するためのタイムアウト(ミリ秒単位)を提供できます。デフォルトは5秒です。
import { afterAll } from 'vitest';
afterAll(async () => {
await stopMocking(); // このメソッドは全てのテスト実行後に呼び出されます
});ここで afterAll は、全てのテストが実行された後に stopMocking メソッドが呼び出されることを保証します。
テストフック
Vitestは、テスト実行中に呼び出すことで、テストが終了したときに状態をクリーンアップできるいくつかのフックを提供しています。
WARNING
これらのフックは、テスト本体の外で呼び出された場合、エラーをスローします。
onTestFinished
このフックは、テストの実行が終了した後に常に呼び出されます。afterEach フックがテスト結果に影響を与える可能性があるため、それらの後に呼び出されます。beforeEach および afterEach と同様に、ExtendedContext オブジェクトを受け取ります。
import { onTestFinished, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});WARNING
テストを並行して実行している場合、Vitestはグローバルフックで並行テストを追跡しないため、常にテストコンテキストから onTestFinished フックを使用してください。
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFinished }) => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});このフックは、再利用可能なロジックを作成する際に特に有用です。
// これは別のファイルに置くことができます
function getTestDb() {
const db = connectMockedDb();
onTestFinished(() => db.close());
return db;
}
test('performs a user query', async () => {
const db = getTestDb();
expect(await db.query('SELECT * from users').perform()).toEqual([]);
});
test('performs an organization query', async () => {
const db = getTestDb();
expect(await db.query('SELECT * from organizations').perform()).toEqual([]);
});TIP
このフックは常に逆順で呼び出され、sequence.hooksオプションの影響を受けません。
onTestFailed
このフックは、テストが失敗した場合にのみ呼び出されます。afterEach フックがテスト結果に影響を与える可能性があるため、それらの後に呼び出されます。beforeEach および afterEach と同様に、ExtendedContext オブジェクトを受け取ります。このフックはデバッグに有用です。
import { onTestFailed, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFailed(({ task }) => {
console.log(task.result.errors);
});
db.query('SELECT * FROM users');
});WARNING
テストを並行して実行している場合、Vitestはグローバルフックで並行テストを追跡しないため、常にテストコンテキストから onTestFailed フックを使用してください。
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFailed }) => {
const db = connectDb();
onTestFailed(({ task }) => {
console.log(task.result.errors);
});
db.query('SELECT * FROM users');
});