Vite + React + TypeScript に テスト環境 Vitest をステップbyステップで作る
Vitestのサイトを見ると、以前はトップページに記載があった
「免責事項:Vitestはまだ開発中であり、安定したものではありません。実運用での使用はお勧めしません。」が消えてました。
- 過去のキャプチャ。Vitestのバージョンは v0.12.6
「DISCLAIMER・・・」が表示されています。
- 2022/05/18 現在「DISCLAIMER・・・」が消えてます。
Vitestのバージョンは 上記と同じ v0.12.6 です。
使ってもいいのかな・・・?ということで Vite + React 環境に Vitest を導入してみました。
vitest
Vitest は Vite 環境で動作する高速なテストフレームワークです。
Vite で作成したアプリケーションであれば、vite.config.ts で設定を共有でき、環境構築が簡単です。
vitest のインストール
まずは vitest をインストールします。
npm install --save-dev vitest
vitest の設定
vitest の 設定は vite.config.ts で行います。
既存の vite.config.ts ファイルの先頭に 「/// <reference types="vitest" />」を追記し Vitest の型への参照を追加します。
+ /// <reference types="vitest" />
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
...
動作確認として関数テストを実行する
動作確認として簡単な関数テストを実行してみます。
src フォルダ内に add.ts と add.test.ts を作成します。
export const add = (a: number, b: number): number => a + b
import { describe, expect, it } from "vitest"
import { add } from "./add"
describe("add", () => {
it("1 + 2 = 3", () => {
const result = add(1, 2)
expect(result).toBe(3)
})
})
以下のコマンドでテストを実行します。
npx vitest
テスト成功です。
vitest はデフォルトで watch モードで実行されます。
watch モードではコードの変更を監視していて、コードに変更があった場合はテストが再実行されます。
watch モードなしで実行するには下記のコマンドでテストを実行します。
npx vitest run
npm run test
でテスト実行できるようにする
npm run test
でテスト実行できるように package.json に追記します。
watch モードなしで実行する 'testrun' も追記しておきました。
"scripts": {
"dev": "vite",
・・・
+ "test": "vitest",
+ "testrun": "vitest run"
}
vitest の API をグローバルAPI として使用できるようにする
デフォルトでは import { describe, expect, it } from "vitest"
と明示的に import しないと vitest の APIが使えません。
jest のように import しなくても使用できるようにするには、vite.config.ts と tsconfig.json を以下のように変更します。
// vite.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
+ globals: true,
},
})
{
"compilerOptions": {
+ "types": ["vitest/globals"]
}
}
以上の設定で add.test.ts ファイルの import を削除してもコンパイルエラーにならず、npm run test
でテスト実行できるようになります。
- // import { describe, expect, it } from "vitest"
import { add } from "./add"
describe("add", () => {
it("1 + 2 = 3", () => {
const result = add(1, 2)
expect(result).toBe(3)
})
})
React コンポーネントのテスト
つづいて React コンポーネントのテストを実行してみます。
コンポーネントのテストを行うには、いくつか追加のライブラリのインストールが必要ですが、
先にコンポーネントとそのテストコードを提示しておきます。
Reactコンポーネント「MyComponent」
import React from 'react'
const title = 'Hello Test'
export function MyComponent() {
return <div>{title}</div>
}
テストコード
「MyComponent」をレンダリングして、その出力内容から「Hello Test」があるかをテストしています。
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import { MyComponent } from './MyComponent'
test('「Hello Test」が描画されている', () => {
render(<MyComponent />)
screen.debug()
expect(screen.getByText('Hello Test')).toBeInTheDocument()
})
上記のテストを実行するために、以下のライブラリをインストールする必要があります。
- jsdom または happy-dom
- @testing-library/react
- @testing-library/jest-dom
1. jsdom または happy-dom をインストール
jsdom とは DOM を JavaScript で実装したものです。
Jest では jsdom が内包されていますが、vitest では別途インストールする必要があります。
happy-dom は jsdom の代替として使用することができて、jsdom より高速に動作するようです。
jsdom と happy-dom のパフォーマンス比較
今回は happy-dom を使用したいと思います。
happy-dom をインストール
npm install --save-dev happy-dom
vite.config.ts
test: {
globals: true,
+ environment: 'happy-dom'
}
2. @testing-library/react のインストール
Reactコンポーネントをテストするためのライブラリです。
テストコードの render メソッドや screen メソッドなどを提供してくれます。npm install --save-dev @testing-library/react
3. @testing-library/jest-dom のインストール
DOM 要素のマッチャーを拡張するユーティリティライブラリーです。
テストコードの toBeInTheDocument メソッドなどを提供してくれます。npm install --save-dev @testing-library/jest-dom
動作確認
npm run test
でテスト実行し、コンポーネントのテストが成功することを確認します。
import '@testing-library/jest-dom'
を書かなくてもいいようにする
テストコードの現状のままだと、テストファイルに毎回「import '@testing-library/jest-dom'」を書く必要があります。
この import を書かなくてもいいように設定します。
- import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import { MyComponent } from './MyComponent'
test('「Hello Test」が描画されている', () => {
render(<MyComponent />)
screen.debug()
expect(screen.getByText('Hello Test')).toBeInTheDocument()
})
設定ファイルを ルート直下に作成します。
ファイル名は何でもいいですが vitest.setup.ts という名前にしました。
vitest.setup.ts に下記コードを書きます。EsLint が怒ってきますが後で設定するので今は無視しておきます。
import '@testing-library/jest-dom'
vite.config.ts の setupFiles プロパティに先ほど作成した設定ファイルを指定します。
setupFiles プロパティは、各テストファイルが実行される直前に実行したいスクリプトファイルを指定するプロパティです。
・・・
export default defineConfig({
・・・
test: {
globals: true,
environment: 'happy-dom',
+ setupFiles: './vitest.setup.ts'
}
})
以上でテストファイルに「import '@testing-library/jest-dom'」を書かなくてもよくなります。
EsLintの設定
以下の EsLint プラグインをインストールします。
npm install eslint-plugin-jest-dom --save-dev
npm install eslint-plugin-testing-library --save-dev
.eslintrc.ymlに設定値を加えます。
env:
browser: true
es2021: true
parser: '@typescript-eslint/parser'
parserOptions:
ecmaFeatures:
jsx: true
ecmaVersion: latest
project: ./tsconfig.json
plugins:
- react
- react-hooks
- '@typescript-eslint'
+ - jest-dom
+ - testing-library
extends:
- plugin:react/recommended
- plugin:react-hooks/recommended
- airbnb
- airbnb-typescript
- prettier
+ overrides:
+ - files:
+ - '**/__tests__/**/*.+(ts|tsx|js)'
+ - '**/?(*.)+(spec|test).+(ts|tsx|js)'
+ extends:
+ - plugin:jest-dom/recommended
+ - plugin:testing-library/react
ignorePatterns:
- vite.config.ts
+ - vitest.setup.ts
・・・
plugins で、jest-dom、testing-library の設定を読み込みます。
overrides で、jest-dom、testing-library の適用範囲を files で指定したファイルに絞ります。
ignorePatterns で、vitest.setup.ts を eslint の適用外に指定します。
VsCode に拡張機能 Vitest をインストール
VsCode に Vitest 拡張機能をインストールすると、テストの実行やデバッグがマウスでポチポチっとできるようになり便利です。
まとめ
他にもフックをテストするためのライブラリなどインストールする必要はありますが、とりあえず vitest の導入ができ簡単なテストができるようになりました。
jest と比べて設定が簡単になるかと思いましたが、少し設定項目が減ったくらいでそこまで大きくはかわりません。
処理速度は jest と比べてかなり速いです。
下記は既存のテストを jest で実行した結果です。
こちらは同じ内容を vitest で実行してみた結果です。
単純に画像の time で比較してはいけないのかもしれませんが、体感でもかなり速いです。
テストが快適になりました🥰
Discussion
ありがとうございます、めちゃくちゃ助かりました!
1点共有ですが、注意で書かれていたhappy-domだとuser-eventがうまく動かない問題、以下バージョンでは正常にクリックできるようになってました。
こちらこそ情報をいただきありごうございます!