環境
- macOS Monterey 12.6
- VSCode
- node.js v18.6.0
- npm 8.13.2
- Typescript ^5.0.2
- vite ^4.4.5
- vitest ^0.34.2
前置き
今テスト始めるならどんな構成がいい?
巷ではjestはオワコン化してきているらしい。単体・結合テストは実行速度がとても重要なわけだが、vitestはjestよりも高速である点が注目されている。
実際、State of javascript 2022でも、JestよりVitestが上位に来ている。(フロントエンドの流行り廃りの変化早すぎて鬱なるわ。。)
従来のjestよりも高速でstate of javascript2022(JavaScriptに興味を持つ世界中のIT技術者3万9472人が回答したアンケートの結果をまとめた)でもJestの利用率を抜いて1位に
本記事で説明すること
本記事では、実務でvitestを用いてテスト環境構築とテストの作成を行うことがあったので、その経験をもとに以下の内容を説明する。なお、関数テストの部分のみ本記事で、それ以降は本記事最後に紹介している別記事を参照されたし(vue、reactそれぞれ別記事で紹介する)
- 関数テスト
- 環境構築
- 関数の実装
- テスト作成
- 実行
- コンポーネントテスト(vue、reactそれぞれ)
- 環境構築
- コンポーネントの実装
- テスト作成
- 実行
- カスタムHooksのテスト(Vueならcomposable関数)
- 関数の実装
- テスト作成
- 実行
reactを使用したケースはこちら
【Vitestで始める単体・結合テスト】ReactコンポーネントとカスタムHooksのテストの環境構築と作成(testing-library/react)
vueを使用したケースはこちら
【Vitestで始める単体・結合テスト】VueコンポーネントとComposable関数のテストの環境構築と作成(testing-library/vue)
【Vitestで始める単体・結合テスト】Vueコンポーネントテストの環境構築と作成(vue-test-utils)
コンポーネントテスト全般のTIPSなどまとめはこちら
【Vitestで始める単体・結合テスト】保守性の高いテストのTIPSやポイント
関数テスト
コンポーネントのテストを実行するためには、まずピュアなJavaScript(TypeScript)の関数テストが実行できる環境を作る必要があるので、そこから説明する
環境構築
vitestの環境構築はまだまだネット上に情報が少ない。そのため以下のvitest公式リポジトリに用意されているような構成を参考にするといい。vueやreact、next.jsなどのそれぞれの技術スタックの組み合わせに応じたサンプル設定を見ることができるので必要に応じて参考されたし。
https://github.com/vitest-dev/vitest/tree/main/examples
Viteプロジェクトの作成(すでにプロジェクトがある場合はスキップしろください)
npm create vite@latest
フレームワーク選択
プロジェクト作る時に使用するUIフレームワークを聞かれるのでお好みのものを選択(今回は例としてvue)
依存関係インストールと開発サーバー起動
npm install && npm run dev
http://localhost:5174/ にアクセスすると、ブラウザで画面を確認できる
Vitest のインストール
アサートメソッド、マッチャーなどを提供するテスト基盤ピュアなJavaScriptやTypeScriptの関数、クラステスト用のviteベースのライブラリ
npm install -D vitest
テスト用ディレクトリの作成
プロジェクトルートに対してtestsディレクトリを作成する
mkdir tests
テストディレクトリ(ファイル)をtypscriptが認識できるようにする
※testファイルもsrc内に置く場合は以下の追加は不要
{
"compilerOptions": {
・・・
},
"include": ["tests/**/*.ts"],
}
Viteの設定ファイル調整
Vitestの型への参照を追加
vite.config.tsの先頭にrefereceを追加
vitest公式より引用
vitest自体を設定するには、Viteのconfigにtestプロパティを追加します。また、vite自身からdefineConfigをインポートする場合は、設定ファイルの先頭にトリプルスラッシュでVitestの型への参照を追加する必要があります。
vite.config.ts
/// <reference types="vitest" />
import { defineConfig } from "vitest/config";
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()], // ここは選択したフレームワークやライブラリごとに自動で指定される
});
※refereceがないと、以下のdefineConfig.testの設定ができないため必要
defineConfig.testのglobalsをtrueにする。これにより、describe, expect, testなどのvitestのapiをテストファイル全体でglobalに扱うことができ、テストファイルごとにimportする必要がなくなる
https://vitest.dev/config/#globals
/// <reference types="vitest" />
import { defineConfig } from "vitest/config";
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()], // ここは選択したフレームワークやライブラリごとに自動で指定される
test: {
globals: true, //here
},
});
以下も忘れずに、
tsconfig.json
{
"compilerOptions": {
・・・割愛
"types": ["vitest/globals"]
},
上記により、各テストファイルでvitestからのimportが不要になる
// something.test.ts
import { describe, it, expect } from "vitest"; ←これが不要になる
import { render } from "@testing-library/vue";
テストコマンドを追加
package.json
{
"name": "vue-vitest",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview",
"test": "vitest" // here
},
関数の実装
Dateオブジェクトをフォーマットして返すシンプルな関数
src/functions/Date/formatDate.ts
export const formatDate = (date: Date) => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
};
テスト作成
tests/functions/Date/formatDate.test.ts
import { formatDate } from "../../../src/functions/Date/formatDate";
describe("formatDate", () => {
test("日付オブジェクトを yyyy-mm-dd フォーマットできる", () => {
const date = new Date("2023-07-28");
const formattedDate = formatDate(date);
expect(formattedDate).toBe("2023-07-28");
});
test("一桁の月と日は0詰め", () => {
const date = new Date("2023-01-02");
const formattedDate = formatDate(date);
expect(formattedDate).toBe("2023-01-02");
});
test("うるう年", () => {
const date = new Date("2024-02-29");
const formattedDate = formatDate(date);
expect(formattedDate).toBe("2024-02-29");
});
});
実行
npm run test
パスエイリアスを設定できるように
srcディレクトリ以下を@のエイリアスでimportできるようにする
// ↓これがいや
import { formatDate } from "../../../src/functions/Date/formatDate";
tsconfig.json
pathsに追加
{
"compilerOptions": {
// here
"paths": {
"@/*": ["./src/*"]
},
・・・
}
}
vite.config.ts
aliasに追加
/// <reference types="vitest/config" />
import { defineConfig } from "vite";
import path from "path";
export default defineConfig({
test: {
// here
alias: {
"@": path.join(__dirname, "/src"),
},
},
});
@でimportできるようになった
tests/functions/Date/formatDate.test.ts
// here
import { formatDate } from "@/functions/Date/formatDate";
describe("formatDate", () => {
・・・
});
コードカバレッジを測定できるように
c8を依存関係に追加
npm install -D @vitest/coverage-v8
vite.config.tsに設定追加
test.coverage部分等を追記。text
が標準出力、lcov
が output ファイルを出力
/// <reference types="vitest" />
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
export default defineConfig({
plugins: [vue()],
test: {
coverage: {
provider: "v8",
all: false, // 未テストのコードもカバレッジに含める
reporter: ["text"], // HTML,Clover,テキスト形式のカバレッジレポート
},
},
});
実行
npx vitest run --coverage
カバレッジがコンソール表示されるとともに、/coverageディレクトリに結果が出力される
本記事ではここまでで、別記事でvue、reactそれぞれのコンポーネントテストがテストできる環境の構築及びテストの作成を行う
まとめ
いかがでしたでしょうk。本記事では、viteベースのvitestで単体・結合テストの環境構築、関数テストの作成、カバレッジ測定の仕組み、パスエイリアスの設定などについて説明しました。今後、jestから置き換えられていくと思いますが、ネット上にはまだそれほど充実した記事はないので、ぜひ参考にして構築してみてください。