T-CREATOR

Jest のインストールと初期設定ガイド

Jest のインストールと初期設定ガイド

現代の Web 開発では、React、Next.js、TypeScript など様々な技術スタックが混在し、プロジェクトごとに異なる環境構成が求められています。そんな中で、Jest を導入する際の設定は、環境によって大きく異なることがあり、適切な設定を行わないとテストが正常に動作しない場合もあります。

この記事では、主要な開発環境における Jest の具体的なインストール手順と初期設定方法を詳しく解説いたします。環境固有の課題を理解し、プロジェクトに最適な設定を構築できるよう、実践的なガイダンスを提供していきます。

現代開発環境の背景

多様なプロジェクト構成の実情

現在の JavaScript エコシステムは非常に豊富で、開発者は目的に応じて最適な技術を選択できるようになりました。しかし、この多様性は設定の複雑さをもたらしています。

フロントエンド開発の選択肢

React を使用する場合でも、Create React App、Vite、Webpack を直接使用する方法など、複数のセットアップ方法があります。さらに、Next.js のようなフルスタックフレームワークを選択する場合もあるでしょう。それぞれが異なるビルドツールやトランスパイラを使用しており、Jest の設定もそれに合わせて調整する必要があります。

バックエンド開発の多様性

Node.js を使用したサーバーサイド開発でも、Express.js を使った従来的なアプローチから、NestJS のようなモダンなフレームワークまで様々です。また、TypeScript を採用するプロジェクトも増加しており、適切な設定が求められます。

モノレポ構成の普及

大規模なプロジェクトでは、複数のパッケージを一つのリポジトリで管理するモノレポ構成が採用されることが増えています。Lerna、Nx、Rush などのツールを使用し、それぞれが独自の設定要件を持っています。

#プロジェクト種別主要技術設定の複雑度
1React SPAReact + Webpack中程度
2Next.js アプリNext.js + TypeScript低い
3Node.js APIExpress + TypeScript中程度
4モノレポLerna + 複数技術高い
5ライブラリ開発TypeScript + Rollup高い

統一的な設定管理の重要性

プロジェクトが複雑になるにつれて、設定の統一性と再利用性が重要になってきます。チーム開発では、新しいメンバーが迅速に開発に参加できるよう、明確で理解しやすい設定が求められるのです。

チーム開発での課題

設定が複雑で文書化されていない場合、新しいメンバーの学習コストが高くなります。また、プロジェクト間で設定が異なると、ノウハウの共有が困難になってしまいます。これらの問題を解決するには、標準化された設定アプローチが必要でしょう。

CI/CD との連携

Jest の設定は、ローカル開発環境だけでなく、GitHub Actions や GitLab CI などの CI/CD パイプラインでも動作する必要があります。環境の違いによる設定の不整合は、デプロイメントの失敗につながる可能性があります。

環境ごとの設定課題

フレームワーク固有の問題

各フレームワークや技術スタックには、Jest を設定する際に特有の課題があります。これらの課題を事前に理解しておくことで、スムーズな設定が可能になります。

React 環境での課題

React コンポーネントをテストする場合、JSX の変換やライフサイクルメソッドの模擬など、特別な設定が必要です。また、React Testing Library との連携や、styled-components などの CSS-in-JS ライブラリとの互換性も考慮する必要があります。

javascript// React特有の課題例
import React from 'react';
import styled from 'styled-components';

const StyledButton = styled.button`
  background-color: blue;
  color: white;
`;

// このコンポーネントをテストするには、適切な設定が必要
export const MyButton = ({ children, onClick }) => {
  return (
    <StyledButton onClick={onClick}>
      {children}
    </StyledButton>
  );
};

Next.js での特殊な要件

Next.js は独自のファイルルーティングシステムと API Routes を持っているため、これらをテストするための特別な設定が必要です。また、サーバーサイドレンダリング(SSR)やスタティック生成(SSG)のテストも考慮する必要があります。

Node.js でのモジュール解決

Node.js 環境では、CommonJS と ES Modules の混在や、パス解決の問題が発生することがあります。特に、相対パスでのインポートが多い場合、Jest の設定で適切にパスマッピングを行う必要があります。

TypeScript、ES6+ 対応の複雑さ

現代の JavaScript 開発では、TypeScript や ES6+ の機能が当たり前に使用されています。しかし、Jest はデフォルトでは CommonJS を前提としているため、適切な変換設定が必要です。

TypeScript 変換の課題

TypeScript のコードを Jest で実行するには、コンパイル工程が必要です。ts-jest を使用する方法と、Babel を使用する方法があり、それぞれにメリット・デメリットがあります。

typescript// TypeScript固有の型定義
interface User {
  id: number;
  name: string;
  roles: string[];
}

// ジェネリクスを使った関数
export function filterUsers<T extends User>(
  users: T[],
  predicate: (user: T) => boolean
): T[] {
  return users.filter(predicate);
}

ES Modules の取り扱い

ES Modules を使用している場合、Jest の設定で適切に変換を行う必要があります。特に、外部ライブラリが ES Modules で配布されている場合、変換の対象に含める設定が重要です。

装飾子(Decorator)の対応

TypeScript でクラスベースの開発を行っている場合、装飾子を使用することがあります。Jest でこれらをテストするには、適切な Babel 設定が必要になります。

環境別最適化ソリューション

プロジェクト種別に応じた設定戦略

それぞれのプロジェクト種別には、最適化された設定戦略があります。これらの戦略を理解することで、効率的で保守性の高い設定を構築できるでしょう。

段階的設定アプローチ

複雑な設定を一度に行うのではなく、基本設定から始めて段階的に機能を追加していく方法です。このアプローチにより、問題が発生した際の原因特定が容易になります。

  1. 基本設定 - 最小限の設定でテスト実行
  2. 変換設定 - TypeScript や JSX の変換追加
  3. モック設定 - 外部依存関係のモック化
  4. カバレッジ設定 - コードカバレッジの測定
  5. 拡張設定 - プロジェクト固有の最適化

設定の分離と組み合わせ

共通設定とプロジェクト固有設定を分離し、必要に応じて組み合わせる戦略です。これにより、設定の再利用性と保守性が向上します。

javascript// 共通設定(jest.config.base.js)
module.exports = {
  testEnvironment: 'node',
  collectCoverage: true,
  coverageReporters: ['text', 'lcov'],
  testMatch: ['**/__tests__/**/*.test.js'],
};

// プロジェクト固有設定(jest.config.js)
const baseConfig = require('./jest.config.base.js');

module.exports = {
  ...baseConfig,
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'],
  moduleNameMapping: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
};

設定の再利用性とメンテナンス性

長期的なプロジェクト運営を考慮すると、設定の再利用性とメンテナンス性が重要になります。これらを実現するためのベストプラクティスを紹介いたします。

プリセット設定の活用

よく使用される設定をプリセットとしてパッケージ化し、複数のプロジェクトで再利用する方法です。チーム内での標準化や、設定の一元管理に効果的でしょう。

設定の文書化

設定ファイルにコメントを充実させ、なぜその設定が必要なのかを明記します。これにより、後からメンテナンスする際の理解が容易になります。

バージョン管理の考慮

Jest や関連するライブラリのバージョンアップに対応するため、設定の互換性を定期的に確認する必要があります。package.json での適切なバージョン指定も重要です。

環境別具体設定

React プロジェクト設定

React プロジェクトで Jest を設定する際の具体的な手順を詳しく解説いたします。Create React App を使用しない場合の手動設定も含めて説明します。

基本インストール

bash# React プロジェクトでの Jest インストール
yarn add --dev jest
yarn add --dev @testing-library/react
yarn add --dev @testing-library/jest-dom
yarn add --dev @testing-library/user-event

# Babel 関連の依存関係
yarn add --dev @babel/preset-react
yarn add --dev babel-jest

設定ファイルの作成

javascript// jest.config.js
module.exports = {
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'],
  moduleNameMapping: {
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
    '^@/(.*)$': '<rootDir>/src/$1',
  },
  transform: {
    '^.+\\.(js|jsx)$': 'babel-jest',
  },
  collectCoverageFrom: [
    'src/**/*.{js,jsx}',
    '!src/index.js',
    '!src/reportWebVitals.js',
  ],
  coverageThreshold: {
    global: {
      branches: 70,
      functions: 70,
      lines: 70,
      statements: 70,
    },
  },
};

Babel 設定

javascript// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', { targets: { node: 'current' } }],
    ['@babel/preset-react', { runtime: 'automatic' }],
  ],
  env: {
    test: {
      plugins: ['@babel/plugin-transform-runtime'],
    },
  },
};

セットアップファイル

javascript// src/setupTests.js
import '@testing-library/jest-dom';

// カスタムマッチャーの追加
expect.extend({
  toBeWithinRange(received, floor, ceiling) {
    const pass = received >= floor && received <= ceiling;
    if (pass) {
      return {
        message: () =>
          `expected ${received} not to be within range ${floor} - ${ceiling}`,
        pass: true,
      };
    } else {
      return {
        message: () =>
          `expected ${received} to be within range ${floor} - ${ceiling}`,
        pass: false,
      };
    }
  },
});

Next.js プロジェクト設定

Next.js プロジェクトでは、フレームワーク固有の機能をテストするための特別な設定が必要です。

Next.js 専用パッケージのインストール

bash# Next.js プロジェクトでの追加パッケージ
yarn add --dev jest
yarn add --dev jest-environment-jsdom
yarn add --dev @testing-library/react
yarn add --dev @testing-library/jest-dom

# Next.js のテストユーティリティ
yarn add --dev next-router-mock

Next.js 専用設定

javascript// jest.config.js
const nextJest = require('next/jest');

const createJestConfig = nextJest({
  // Next.js アプリのディレクトリを指定
  dir: './',
});

const customJestConfig = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  moduleNameMapping: {
    '^@/components/(.*)$': '<rootDir>/components/$1',
    '^@/pages/(.*)$': '<rootDir>/pages/$1',
    '^@/lib/(.*)$': '<rootDir>/lib/$1',
  },
  testEnvironment: 'jest-environment-jsdom',
  collectCoverageFrom: [
    '**/*.{js,jsx,ts,tsx}',
    '!**/*.d.ts',
    '!**/node_modules/**',
    '!**/.next/**',
  ],
};

module.exports = createJestConfig(customJestConfig);

API Routes のテスト設定

javascript// __tests__/api/users.test.js
import { createMocks } from 'node-mocks-http';
import handler from '../../pages/api/users';

describe('/api/users', () => {
  test('GET リクエストの処理', async () => {
    const { req, res } = createMocks({
      method: 'GET',
    });

    await handler(req, res);

    expect(res._getStatusCode()).toBe(200);
    const data = JSON.parse(res._getData());
    expect(data).toHaveProperty('users');
  });
});

TypeScript プロジェクト設定

TypeScript プロジェクトでは、型チェックとコンパイル設定が重要になります。

TypeScript 関連パッケージ

bash# TypeScript プロジェクトでの Jest 設定
yarn add --dev jest
yarn add --dev ts-jest
yarn add --dev @types/jest
yarn add --dev typescript

# TypeScript 用テストライブラリ
yarn add --dev @testing-library/jest-dom

TypeScript 設定ファイル

javascript// jest.config.js
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  roots: ['<rootDir>/src'],
  testMatch: [
    '**/__tests__/**/*.+(ts|tsx|js)',
    '**/*.(test|spec).+(ts|tsx|js)',
  ],
  transform: {
    '^.+\\.(ts|tsx)$': 'ts-jest',
  },
  collectCoverageFrom: [
    'src/**/*.{ts,tsx}',
    '!src/**/*.d.ts',
    '!src/**/index.ts',
  ],
  moduleNameMapping: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
  setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts'],
};

TypeScript 設定の調整

json// tsconfig.json でのテスト向け設定
{
  "compilerOptions": {
    "target": "es2020",
    "lib": ["dom", "dom.iterable", "es6"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  "include": ["src/**/*", "**/*.test.ts", "**/*.test.tsx"],
  "exclude": ["node_modules", "build"]
}

Node.js プロジェクト設定

Node.js サーバーサイドプロジェクトでの Jest 設定について説明いたします。

Node.js プロジェクトでのインストール

bash# Node.js プロジェクトでの基本セットアップ
yarn add --dev jest
yarn add --dev supertest
yarn add --dev @types/supertest

# ES Modules 使用時
yarn add --dev babel-jest
yarn add --dev @babel/preset-env

Node.js 向け設定

javascript// jest.config.js
module.exports = {
  testEnvironment: 'node',
  roots: ['<rootDir>/src', '<rootDir>/tests'],
  testMatch: [
    '**/__tests__/**/*.js',
    '**/*.(test|spec).js',
  ],
  collectCoverageFrom: [
    'src/**/*.js',
    '!src/server.js',
    '!src/**/index.js',
  ],
  coverageDirectory: 'coverage',
  coverageReporters: ['text', 'lcov', 'html'],
  setupFilesAfterEnv: ['<rootDir>/tests/setup.js'],
  globalTeardown: '<rootDir>/tests/teardown.js',
  testTimeout: 10000,
};

Express.js API のテスト例

javascript// tests/api.test.js
const request = require('supertest');
const app = require('../src/app');

describe('User API', () => {
  test('GET /api/users', async () => {
    const response = await request(app)
      .get('/api/users')
      .expect('Content-Type', /json/)
      .expect(200);

    expect(response.body).toHaveProperty('users');
    expect(Array.isArray(response.body.users)).toBe(true);
  });

  test('POST /api/users', async () => {
    const newUser = {
      name: 'テストユーザー',
      email: 'test@example.com',
    };

    const response = await request(app)
      .post('/api/users')
      .send(newUser)
      .expect('Content-Type', /json/)
      .expect(201);

    expect(response.body).toHaveProperty('id');
    expect(response.body.name).toBe(newUser.name);
  });
});

モノレポ環境での設定

大規模プロジェクトでよく採用されるモノレポ環境での Jest 設定について解説します。

Lerna を使用したモノレポ設定

bash# ルートレベルでの Jest インストール
yarn add --dev jest
yarn add --dev lerna

# 各パッケージでの設定は継承

ルート設定ファイル

javascript// jest.config.js (ルート)
module.exports = {
  projects: ['<rootDir>/packages/*/jest.config.js'],
  collectCoverageFrom: ['packages/*/src/**/*.{js,ts,tsx}'],
  coverageDirectory: '<rootDir>/coverage',
  coverageReporters: ['text', 'lcov', 'html'],
};

パッケージ個別設定

javascript// packages/ui-components/jest.config.js
module.exports = {
  displayName: 'ui-components',
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'],
  moduleNameMapping: {
    '\\.(css|less|scss)$': 'identity-obj-proxy',
  },
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': [
      'babel-jest',
      {
        configFile: '<rootDir>/../../babel.config.js',
      },
    ],
  },
};

Workspace 設定

json// package.json (ルート)
{
  "name": "monorepo-project",
  "private": true,
  "workspaces": ["packages/*"],
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage"
  }
}
#環境種別主要な設定ポイント難易度
1ReactJSX 変換、CSS モック中程度
2Next.jsルーター モック、API テスト低い
3TypeScript型チェック、パスマッピング中程度
4Node.jsテスト環境、API テスト中程度
5モノレポプロジェクト分割、設定継承高い

まとめ

Jest のインストールと初期設定は、プロジェクトの技術スタックによって大きく異なります。この記事では、主要な開発環境における具体的な設定方法を詳しく解説いたしました。

環境別設定の重要性

React、Next.js、TypeScript、Node.js、モノレポなど、それぞれの環境には固有の要件と課題があります。適切な設定を行うことで、テストの実行速度向上、保守性の確保、チーム開発の効率化を実現できるでしょう。

設定のベストプラクティス

段階的な設定アプローチ、設定の分離と再利用、適切な文書化により、長期的に保守しやすい設定を構築できます。特に、チーム開発では統一された設定標準が重要になります。

継続的な改善

Jest や関連ライブラリは継続的にアップデートされているため、定期的な設定の見直しと最適化が必要です。新しい機能やベストプラクティスを取り入れながら、プロジェクトに最適な設定を維持していきましょう。

適切な Jest 設定により、開発プロセスの品質と効率が大幅に向上します。この記事の設定例を参考に、皆さんのプロジェクトに最適な Jest 環境を構築してみてください。

関連リンク