Jestによるテスト入門
Jestとは
JavaScriptのテストフレームワーク。Facebook社が開発したJavaScriptのテストツールで、テストランナー本体です。テストの実行、アサーション(expect)、モック機能などの基本機能を提供します。
アサーションとは、プログラミングのデバッグやテスト中にその条件が「真」であることを表明し、「偽」であった場合には処理を止めてエラーを発生させること。エラー発生時点で処理が止まるため、バグの早期発見になります。
使用できるプロジェクト
- JavaScript
- TypeScript
- Node.js
- React
そもそもテストとは
なぜテストするのか
テストとはコードが意図したとおりに動作するかを確認する作業です。
コードの信頼性担保: リファクタリング時の不具合防止
ドキュメント代わり: テストコードが仕様書になる
開発速度向上: 手動確認の時間削減
テストの種類
単体テスト: 関数・コンポーネント単位
統合テスト: 複数コンポーネントの連携
E2Eテスト: ブラウザ操作の自動化
Jestの特徴
ゼロコンフィグ
Jestは、ほとんどのJavaScriptプロジェクトで、設定なしですぐに使えるようにすることを目指しています。
スナップショット
大きなオブジェクトを簡単に追跡するテストを作成できます。スナップショットはテストと一緒に保存するか、インラインで埋め込むことができます。
独立したプロセスと実行速度の高速化
テストは、パフォーマンスを最大化するために独自のプロセスで実行することで並列化されます。
豊富なAPI
it から expect まで、Jestはツールキット全体を一箇所にまとめています。ドキュメントも充実し、メンテナンスも行き届いており、非常に優れています。
※公式サイトより、Google翻訳とAI翻訳したものを記載しています
環境構築
Jestのインストール
npm install --save-dev jest
# pnpmの場合
pnpm add -D jest
Next.jsでのインストール
Next.jsプロジェクトの場合は、以下のライブラリをまとめてインストールします。
pnpm add -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom ts-node @types/jest
参考: Next.js公式ドキュメント - Testing with Jest
インストールしたライブラリの役割
| ライブラリ | 役割 |
|---|---|
jest |
テストランナー本体(テスト実行・アサーション) |
jest-environment-jsdom |
ブラウザ環境をシミュレート(DOM操作のテスト用) |
@testing-library/react |
Reactコンポーネントのテスト用 |
@testing-library/dom |
DOM操作のテスト用(React Testing Libraryの依存) |
@testing-library/jest-dom |
DOMアサーション拡張(toBeInDocument等) |
ts-node |
TypeScriptをNode.jsで実行(設定ファイル用) |
@types/jest |
Jestの型定義(TypeScript用) |
package.jsonの設定
pakage.jsonで以下を追加しておきます。
"scripts": {
"test": "jest"
}
Next.js用の設定ファイル
プロジェクトルートに jest.config.ts を作成:
import type { Config } from 'jest'
import nextJest from 'next/jest.js'
const createJestConfig = nextJest({
dir: './',
})
const config: Config = {
coverageProvider: 'v8',
testEnvironment: 'jsdom',
}
export default createJestConfig(config)
それぞれの設定の持つ意味
-
coverageProvider: 'v8'→ カバレッジ測定ツール -
testEnvironment: 'jsdom'→ ブラウザ環境をシミュレート -
createJestConfig→ Next.jsの内部設定と統合
テストの実行
npm test
# または
pnpm test
使用できるCLIコマンド
テスト実行時に使える便利なオプション:
# ファイル変更を監視して自動実行
npm test -- --watch
# カバレッジレポートを生成
npm test -- --coverage
# 特定のファイルだけテスト
npm test navigation.test.ts
実際のテストコード例
ユーティリティ関数のテスト
実装コード:
// lib/utils/navigation.ts
export function isCurrent(pathname: string, href: string): boolean {
const path = pathname.split('?')[0];
return path === href;
}
テストコード:
// lib/utils/navigation.test.ts
import { isCurrent } from "./navigation";
test('同じパスの場合はtrueを返す', () => {
expect(isCurrent('/', '/')).toBe(true);
expect(isCurrent('/works', '/works')).toBe(true);
});
test('異なるパスの場合はfalseを返す', () => {
expect(isCurrent('/works', '/')).toBe(false);
expect(isCurrent('/works/123', '/articles')).toBe(false);
expect(isCurrent('/articles?sort=liked_count&order=desc', '/works')).toBe(false);
});
test('クエリパラメータがあってもパスが同じならtrueを返す', () => {
expect(isCurrent('/articles?sort=liked_count&order=desc', '/articles')).toBe(true);
expect(isCurrent('/articles?sort=liked_count&order=asc&searchQuery=keyword', '/articles')).toBe(true);
});
Jestの基本的なアサーション
| アサーション | 意味 | 例 |
|---|---|---|
toBe() |
厳密等価(===)・値の比較 | expect(1 + 1).toBe(2) |
toEqual() |
オブジェクト・配列の比較 | expect([1, 2]).toEqual([1, 2]) |
toBeTruthy() |
真値かどうか | expect('hello').toBeTruthy() |
toBeFalsy() |
偽値かどうか | expect(0).toBeFalsy() |
toContain() |
配列に含まれるか | expect([1, 2, 3]).toContain(2) |
toThrow() |
エラーを投げるか | expect(() => fn()).toThrow() |
Discussion