移行ガイド
Vitest 2.0 への移行
デフォルトのプールは forks
です
Vitest 2.0 では、安定性向上のため、pool
のデフォルト設定が 'forks'
に変更されました。詳細な動機については、PR をご参照ください。
pool
を指定せずに poolOptions
を使用していた場合、設定を更新する必要があるかもしれません。
export default defineConfig({
test: {
poolOptions: {
threads: {
singleThread: true,
},
forks: {
singleFork: true,
},
},
},
});
フックはスタックで実行されます
Vitest 2.0 より前は、すべてのフックが並行して実行されていました。2.0 では、すべてのフックが順次実行されます。さらに、afterAll
/afterEach
フックは逆順に実行されます。
フックの並行実行に戻すには、sequence.hooks
を 'parallel'
に変更します。
export default defineConfig({
test: {
sequence: {
hooks: 'parallel',
},
},
});
suite.concurrent
はすべてのテストを並行して実行します
以前は、スイートで concurrent
を指定すると、並行テストがスイートごとにグループ化され、順次実行されていました。現在は、Jest の動作に倣い、すべてのテストが同時に実行されます(maxConcurrency
の制限に従います)。
V8 カバレッジの coverage.ignoreEmptyLines
がデフォルトで有効になりました
coverage.ignoreEmptyLines
のデフォルト値が true
になりました。この変更はコードカバレッジレポートに影響を及ぼす可能性があり、一部のプロジェクトではカバレッジしきい値の調整が必要になる場合があります。この調整は、coverage.provider
が 'v8'
の場合のデフォルト設定にのみ影響します。
watchExclude
オプションの削除
Vitest は Vite のウォッチャーを使用します。ファイルやディレクトリを除外するには、server.watch.ignored
に追加します。
export default defineConfig({
server: {
watch: {
ignored: ['!node_modules/examplejs'],
},
},
});
--segfault-retry
が削除されました
デフォルトのプールが変更されたため、このオプションは不要になりました。セグメンテーション違反エラーが発生した場合は、'forks'
プールに切り替えてみてください。問題が解決しない場合は、再現手順を添えて新しい issue を開いてください。
スイートタスク内の空のタスクが削除されました
これは、高度なタスク API への変更です。以前は、.suite
を辿っていくと、ファイルタスクの代わりに使われていた空の内部スイートに最終的に到達していました。
これにより、.suite
はオプションになります。タスクがトップレベルで定義されている場合、スイートは存在しません。すべてのタスク(ファイルタスク自体も含むため、無限再帰に陥らないよう注意が必要ですが)に存在するようになった .file
プロパティにフォールバックできます。
この変更により、expect.getState().currentTestName
からファイルが削除され、expect.getState().testPath
が必須になりました。
task.meta
が JSON レポーターに追加されました
JSON レポーターは、すべてのアサーション結果に対して task.meta
を出力するようになりました。
モック関数のジェネリック型が簡素化されました (例: vi.fn<T>
, Mock<T>
)
以前の vi.fn<TArgs, TReturn>
は、引数と戻り値の型をそれぞれ別のジェネリック型として受け入れていました。これは、使用を簡略化するために、関数型 vi.fn<T>
を直接受け入れるように変更されました。
import { type Mock, vi } from 'vitest';
const add = (x: number, y: number): number => x + y;
// vi.fn<T> の使用
const mockAdd = vi.fn<Parameters<typeof add>, ReturnType<typeof add>>();
const mockAdd = vi.fn<typeof add>();
// Mock<T> の使用
const mockAdd: Mock<Parameters<typeof add>, ReturnType<typeof add>> = vi.fn();
const mockAdd: Mock<typeof add> = vi.fn();
解決済みの mock.results
へのアクセス
以前の Vitest では、関数が Promise を返した場合、mock.results
の値が解決されていました。現在は、返された Promise が解決または拒否された場合にのみ値が設定される、別の mock.settledResults
プロパティがあります。
const fn = vi.fn().mockResolvedValueOnce('result');
await fn();
const result = fn.mock.results[0]; // 'result'
const result = fn.mock.results[0]; // 'Promise<result>'
const settledResult = fn.mock.settledResults[0]; // 'result'
この変更に伴い、以前 toHaveReturned
を使用していた場合の移行を容易にするために、toHaveReturned
と同様の新しい toHaveResolved*
マッチャーも導入されました。
const fn = vi.fn().mockResolvedValueOnce('result');
await fn();
expect(fn).toHaveReturned('result');
expect(fn).toHaveResolved('result');
ブラウザモード
Vitest ブラウザモードは、ベータサイクル中に多くの変更が行われました。ブラウザモードに関する私たちの考え方については、GitHub ディスカッションページをご覧ください。
変更のほとんどは追加的なものでしたが、いくつかの小さな破壊的変更がありました。
none
プロバイダーがpreview
にリネームされました #5842preview
プロバイダーがデフォルトになりました #5842indexScripts
がorchestratorScripts
にリネームされました #5842
非推奨オプションの削除
いくつかの非推奨オプションが廃止されました。
vitest typecheck
コマンド - 代わりにvitest --typecheck
を使用してくださいVITEST_JUNIT_CLASSNAME
およびVITEST_JUNIT_SUITE_NAME
環境変数(代わりにレポーターオプションを使用してください)c8
カバレッジのチェック(代わりに coverage-v8 を使用してください)vitest
からのSnapshotEnvironment
のエクスポート - 代わりにvitest/snapshot
からインポートしてくださいSpyInstance
はMockInstance
に置き換えられました
Vitest 1.0 への移行
最小要件
Vitest 1.0 は Vite 5.0 および Node.js 18 以降が必要です。
すべての @vitest/*
サブパッケージは Vitest バージョン 1.0 を必要とします。
スナップショットの更新 #3961
スナップショット内の引用符はエスケープされなくなり、すべてのスナップショットは、文字列が単一行であってもバッククォート (`) を使用するようになりました。
- 引用符はエスケープされなくなりました。
expect({ foo: 'bar' }).toMatchInlineSnapshot(`
Object {
- \\"foo\\": \\"bar\\",
+ "foo": "bar",
}
`)
- 1行のスナップショットは、
"
ではなく "`" 引用符を使用するようになりました。
- expect('some string').toMatchInlineSnapshot('"some string"')
+ expect('some string').toMatchInlineSnapshot(`"some string"`)
また、@vitest/snapshot
パッケージにも変更がありました。直接使用していない場合は、何も変更する必要はありません。
equalityCheck
メソッドをオーバーライドするためだけにSnapshotClient
を拡張する必要がなくなりました。インスタンスを初期化する際にisEqual
として渡すだけです。client.setTest
はclient.startCurrentRun
にリネームされました。client.resetCurrent
はclient.finishCurrentRun
にリネームされました。
プールの標準化 #4172
ランナーをニーズに応じて簡単に設定できるよう、多くの設定オプションを削除しました。--threads
やその他の関連フラグに依存している場合は、移行例をご参照ください。
--threads
は--pool=threads
になりました--no-threads
は--pool=forks
になりました--single-thread
は--poolOptions.threads.singleThread
になりました--experimental-vm-threads
は--pool=vmThreads
になりました--experimental-vm-worker-memory-limit
は--poolOptions.vmThreads.memoryLimit
になりました--isolate
は--poolOptions.<pool-name>.isolate
およびbrowser.isolate
になりましたtest.maxThreads
はtest.poolOptions.<pool-name>.maxThreads
になりましたtest.minThreads
はtest.poolOptions.<pool-name>.minThreads
になりましたtest.useAtomics
はtest.poolOptions.<pool-name>.useAtomics
になりましたtest.poolMatchGlobs.child_process
はtest.poolMatchGlobs.forks
になりましたtest.poolMatchGlobs.experimentalVmThreads
はtest.poolMatchGlobs.vmThreads
になりました
{
scripts: {
- "test": "vitest --no-threads"
// 同一の動作の場合:
+ "test": "vitest --pool forks --poolOptions.forks.singleFork"
// または複数の並列フォークの場合:
+ "test": "vitest --pool forks"
}
}
{
scripts: {
- "test": "vitest --experimental-vm-threads"
+ "test": "vitest --pool vmThreads"
}
}
{
scripts: {
- "test": "vitest --isolate false"
+ "test": "vitest --poolOptions.threads.isolate false"
}
}
{
scripts: {
- "test": "vitest --no-threads --isolate false"
+ "test": "vitest --pool forks --poolOptions.forks.isolate false"
}
}
カバレッジの変更 #4265, #4442
coverage.all
オプションがデフォルトで有効になりました。これは、coverage.include
パターンに一致するすべてのプロジェクトファイルが、実行されなくても処理されることを意味します。
カバレッジしきい値 API の形式が変更され、グロブパターンを使用して特定のファイルにしきい値を指定できるようになりました。
export default defineConfig({
test: {
coverage: {
- perFile: true,
- thresholdAutoUpdate: true,
- 100: true,
- lines: 100,
- functions: 100,
- branches: 100,
- statements: 100,
+ thresholds: {
+ perFile: true,
+ autoUpdate: true,
+ 100: true,
+ lines: 100,
+ functions: 100,
+ branches: 100,
+ statements: 100,
+ }
}
}
})
モック型 #4400
Jest スタイルの「Mock」命名に合わせるため、いくつかの型が削除されました。
- import { EnhancedSpy, SpyInstance } from 'vitest'
+ import { MockInstance } from 'vitest'
WARNING
SpyInstance
は MockInstance
に置き換えられ、次のメジャーリリースで削除されます。
タイマーモック #3925
vi.useFakeTimers()
は、process.nextTick
を自動的にモックしなくなりました。 vi.useFakeTimers({ toFake: ['nextTick'] })
を使用して明示的に指定することで、process.nextTick
をモックすることは引き続き可能です。
ただし、--pool=forks
を使用している場合、process.nextTick
のモックはできません。process.nextTick
のモックが必要な場合は、別の --pool
オプションを使用してください。
Jest からの移行
Vitest は Jest 互換の API で設計されており、Jest からの移行を可能な限りシンプルにすることを目指しています。しかし、以下の違いに遭遇する可能性があります。
グローバルなAPIのデフォルト設定
Jest はデフォルトでグローバル API を有効にしていますが、Vitest はそうではありません。globals
設定 を介してグローバルを有効にするか、vitest
モジュールからのインポートを使用するようにコードを更新することができます。
グローバルを無効にしたままにする場合、testing-library
のような一般的なライブラリは、DOM の自動クリーンアップを実行しないことに注意してください。
モジュールモック
Jest でモジュールをモックする場合、ファクトリー関数の引数の戻り値はデフォルトのエクスポートです。Vitest では、ファクトリー関数の引数は各エクスポートが明示的に定義されたオブジェクトを返す必要があります。例えば、以下の jest.mock
は次のように更新する必要があります。
jest.mock('./some-path', () => 'hello');
vi.mock('./some-path', () => ({
default: 'hello',
}));
詳細については、vi.mock
API セクションを参照してください。
自動モックの動作
Jest とは異なり、<root>/__mocks__
内のモックされたモジュールは、vi.mock()
が呼び出されない限りロードされません。Jest のようにすべてのテストでモックする必要がある場合は、setupFiles
内でモックできます。
モックされたパッケージのオリジナルをインポートする
パッケージを部分的にモックを行っている場合、以前は Jest の関数 requireActual
を使用していたかもしれません。Vitest では、これらの呼び出しを vi.importActual
に置き換える必要があります。
const { cloneDeep } = jest.requireActual('lodash/cloneDeep');
const { cloneDeep } = await vi.importActual('lodash/cloneDeep');
外部ライブラリへのモックの拡張
Jest がデフォルトで行うように、モジュールをモックし、このモックを同じモジュールを使用する他の外部ライブラリに拡張したい場合は、どのサードパーティのライブラリをモックしたいかを明示的に指定する必要があります。そのためには、server.deps.inline を使用して、外部ライブラリをソースコードの一部として扱うように設定します。
server.deps.inline: ["lib-name"]
expect.getState().currentTestName
Vitest の test
名は、スイートとテストを区別しやすくするために >
記号で結合されますが、Jest は空白 () を使用します。
- `${describeTitle} ${testTitle}`
+ `${describeTitle} > ${testTitle}`
環境変数
Jest と同様に、Vitest は NODE_ENV
が設定されていない場合、test
に設定します。Vitest には JEST_WORKER_ID
に相当する VITEST_POOL_ID
(常に maxThreads
以下)があります。これに依存している場合は、名前の変更を忘れないでください。Vitest はまた、実行中のワーカーのユニークな ID である VITEST_WORKER_ID
も公開します。この数値は maxThreads
の影響を受けず、作成されるワーカーごとに増加します。
プロパティの置換
オブジェクトを変更したい場合、Jest では replaceProperty API を使用しますが、Vitest でも同様に vi.stubEnv
または vi.spyOn
を使用できます。
Done コールバック
Vitest v0.10.0 以降、テストを宣言するコールバック形式は非推奨になりました。async
/await
関数を使用するように書き換えるか、Promise を使用してコールバック形式を模倣できます。
it('should work', (done) => { // [!code --]
it('should work', () => new Promise(done => { // [!code ++]
// ...
done()
}) // [!code --]
})) // [!code ++]
フック
beforeAll
/beforeEach
フックは Vitest でティアダウン用の関数を返すことができます。そのため、undefined
または null
以外を返すフックの宣言を書き換える必要があるかもしれません。
beforeEach(() => setActivePinia(createTestingPinia()));
beforeEach(() => {
setActivePinia(createTestingPinia());
});
Jest ではフックは順次(一つずつ)呼び出されます。デフォルトでは、Vitest はフックを並行して実行します。Jest の動作を使用するには、sequence.hooks
オプションを更新します。
export default defineConfig({
test: {
sequence: {
hooks: 'list',
},
},
});
型
Vitest には jest
名前空間に相当するものが存在しないため、vitest
から直接型をインポートする必要があります。
let fn: jest.Mock<(name: string) => number>;
import type { Mock } from 'vitest';
let fn: Mock<(name: string) => number>;
タイマー
Vitest は Jest のレガシータイマーをサポートしていません。
タイムアウト
jest.setTimeout
を使用していた場合、vi.setConfig
に移行する必要があります。
jest.setTimeout(5_000);
vi.setConfig({ testTimeout: 5_000 });
Vue スナップショット
これは Jest 固有の機能ではありませんが、以前 Jest を vue-cli プリセットを使用していた場合、jest-serializer-vue
パッケージをインストールし、setupFiles 内で使用する必要があります。
import { defineConfig } from 'vite';
export default defineConfig({
test: {
setupFiles: ['./tests/unit/setup.js'],
},
});
import vueSnapshotSerializer from 'jest-serializer-vue';
expect.addSnapshotSerializer(vueSnapshotSerializer);
そうしないと、スナップショットに多くのエスケープされた "
文字が含まれることになります。