Open6

VitestのDocを読む

KeitaUenishiKeitaUenishi

Viteは、一般的なウェブパターンをすぐにサポートし、グロブのインポートやSSRプリミティブのような機能、そして多くのプラグインや統合により、活気あるエコシステムを育んでいる。 その開発とビルドのストーリーは成功の鍵だ。 ドキュメントについては、Viteを搭載したSSGベースの代替ツールがいくつかある。 しかし、Viteのユニットテストの話は明確ではない。 Jestのような既存のオプションは別の文脈で作られたものだ。 JestとViteの間には重複が多く、ユーザーは2つの異なるパイプラインを設定することを余儀なくされている。

テスト中にファイルを変換するために Vite dev server を使用することで、ソースファイルを変換する複雑さに対処する必要がなく、テスト中に最高の DX を提供することだけに集中できるシンプルなランナーを作成することができます。 vite.config.js を通して)アプリの同じ設定を使用するテストランナーは、開発、ビルド、テスト時に共通の変換パイプラインを共有します。 同じプラグイン API で拡張可能で、あなたやあなたのツールのメンテナが Vite とファーストクラスの統合を提供できます。 Viteのインスタントホットモジュールリロード(HMR)のようなDXの改良を活用し、最初からViteを意識して作られたツール。 これがVitestであり、Viteを搭載した次世代のテストフレームワークです。

Jestの大規模な採用を受けて、Vitestは互換性のあるAPIを提供し、ほとんどのプロジェクトでJestをドロップインで置き換えることができます。 また、ユニットテストをセットアップする際に必要となる最も一般的な機能も含まれています(モッキング、スナップショット、カバレッジ)。 Vitestはパフォーマンスを重視しており、Workerスレッドを使って可能な限り並列に実行します。 いくつかのポートでは、テストの実行速度が一桁速くなっている。 ウォッチモードはデフォルトで有効になっており、Viteがデベロッパーファーストエクスペリエンスを推し進める方法と一致している。 DXのこのような改善にもかかわらず、Vitestは依存関係を注意深く選択することで(あるいは必要な部分を直接インライン化することで)軽量さを維持している。

https://vitest.dev/guide/why.html#the-need-for-a-vite-native-test-runner

KeitaUenishiKeitaUenishi

Features

Threads

デフォルトでは、Vitest は Tinypool (Piscina の軽量フォーク) を介して node:child_process を使用して複数のプロセスでテストファイルを実行し、テストを同時に実行できます。 テストスイートをさらに高速化したい場合は、-pool=threads を有効にして node:worker_threads を使用してテストを実行することを検討してください(この設定では動作しないパッケージもあるので注意してください)。

Running Tests Concurrently

連続するテストでは、.concurrent を使用して並行して開始する。
スイートで.concurrentを使用すると、スイート内のすべてのテストが並行して開始されます。

import { describe, it } from 'vitest'

// All tests within this suite will be started in parallel
describe.concurrent('suite', () => {
  it('concurrent test 1', async ({ expect }) => { /* ... */ })
  it('concurrent test 2', async ({ expect }) => { /* ... */ })
  it.concurrent('concurrent test 3', async ({ expect }) => { /* ... */ })
})

https://vitest.dev/guide/features.html#running-tests-concurrently

Mocking

VitestはDOMとブラウザAPIをモックするためにhappy-domとjsdomの両方をサポートしています。 これらはVitestには付属していませんので、別途インストールする必要があります:

In-Source Testing

Vitestはまた、Rustのモジュールテストと同様に、実装と一緒にソースコード内でテストを実行する方法も提供している。

// src/index.ts

// the implementation
export function add(...args: number[]): number {
  return args.reduce((a, b) => a + b, 0)
}

// in-source test suites
if (import.meta.vitest) {
  const { it, expect } = import.meta.vitest
  it('add', () => {
    expect(add()).toBe(0)
    expect(add(1)).toBe(1)
    expect(add(1, 2, 3)).toBe(6)
  })
}
KeitaUenishiKeitaUenishi

Test Filltering

https://vitest.dev/guide/filtering.html#test-filtering

オプションで、ミリ秒単位のタイムアウトを第3引数としてテストに渡すことができる。 デフォルトは5秒である。

import { test } from 'vitest'

test('name', async () => { /* ... */ }, 1000)
  • .skip を使用すると、指定したスイートやテストの実行を回避できる
  • .only を使用すると、指定したスイートやテストのみを実行
  • .todo を使用すると実装すべきスイートやテストをスタブ化する
KeitaUenishiKeitaUenishi

Mocking

https://vitest.dev/guide/mocking.html

テストを書くとき、内部(あるいは外部)サービスの「偽」バージョンを作る必要が出てくるのは時間の問題です。 これは一般にモッキングと呼ばれています。 Vitestは、viヘルパーを通してあなたを助けるユーティリティ関数を提供します。 vitest'から{ vi }をインポートするか、グローバルにアクセスすることができる(グローバル・コンフィギュレーションが有効な場合)。

WARNING
テスト実行の前後には必ずモックをクリアするかリストアして、実行中のモックの状態変更を元に戻してください! 詳しくは mockReset のドキュメントを参照してください。

vi.stubGlobalヘルパーを使えば、jsdomやnodeに存在しないグローバル変数をモックすることができる。 これはグローバル変数の値をglobalThisオブジェクトに入れます。
https://vitest.dev/guide/mocking.html#globals