T-CREATOR

jest.config.js の設定ポイントと活用法

jest.config.js の設定ポイントと活用法

Jest を使ったテスト環境を構築する際、設定ファイルの理解は欠かせません。適切な設定により、テストの実行速度向上、開発効率の改善、そしてプロジェクトの要件に合わせた柔軟なテスト環境を実現できます。

本記事では、jest.config.js の主要な設定オプションを体系的に解説し、実際のプロジェクトで活用できる実践的な設定例をご紹介します。初心者の方でも理解しやすいよう、各設定項目の役割と使い方を丁寧に説明していきますね。

jest.config.js の基本構造

Jest の設定ファイルは、プロジェクトのルートディレクトリに配置する JavaScript ファイルです。設定オブジェクトをエクスポートすることで、Jest の動作をカスタマイズできます。

基本的なファイル構造

javascript// jest.config.js
module.exports = {
  // テスト実行環境の設定
  testEnvironment: 'jsdom',

  // テストファイルの検索パターン
  testMatch: [
    '**/__tests__/**/*.(js|jsx|ts|tsx)',
    '**/*.(test|spec).(js|jsx|ts|tsx)',
  ],

  // セットアップファイルの指定
  setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'],

  // モジュール名のマッピング
  moduleNameMapping: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
};

この基本構造を理解することで、プロジェクトの要件に応じた設定を組み立てられるようになります。

設定ファイルの種類と優先順位

Jest は複数の設定方法をサポートしており、以下の優先順位で設定が適用されます。

優先度設定方法ファイル名
1コマンドライン引数-
2jest.config.jsjest.config.js
3package.json の jest フィールドpackage.json
4デフォルト設定-
javascript// package.json での設定例
{
  "jest": {
    "testEnvironment": "node",
    "collectCoverage": true
  }
}

プロジェクトの規模が大きくなるにつれて、専用の設定ファイルを使用することをおすすめします。

テスト実行に関する設定

テストファイルの検索や実行環境に関する設定は、Jest の基本的な動作を決定する重要な要素です。

testMatch と testIgnorePatterns

testMatch は、Jest がテストファイルとして認識するファイルパターンを指定します。

javascriptmodule.exports = {
  // テストファイルのパターン指定
  testMatch: [
    // __tests__ ディレクトリ内のファイル
    '**/__tests__/**/*.(js|jsx|ts|tsx)',

    // .test または .spec 拡張子のファイル
    '**/*.(test|spec).(js|jsx|ts|tsx)',

    // 特定ディレクトリのテストファイル
    '<rootDir>/tests/**/*.test.js',
  ],

  // テスト対象から除外するパターン
  testIgnorePatterns: [
    '/node_modules/',
    '/build/',
    '/dist/',
    '/.next/',
    '/coverage/',
  ],
};

実際のプロジェクトでは、以下のような使い分けが効果的です。

javascript// 大規模プロジェクト向けの設定例
module.exports = {
  testMatch: [
    // ユニットテスト
    '<rootDir>/src/**/__tests__/**/*.test.(js|ts)',

    // 統合テスト
    '<rootDir>/tests/integration/**/*.test.(js|ts)',

    // E2Eテスト(別途実行)
    // '<rootDir>/tests/e2e/**/*.test.(js|ts)'
  ],

  testIgnorePatterns: [
    '/node_modules/',
    '/build/',
    '/.next/',
    '/storybook-static/',
    // 一時的にスキップしたいテスト
    '**/*.skip.test.(js|ts)',
  ],
};

testEnvironment と setupFiles

testEnvironment は、テストが実行される環境を指定します。

javascriptmodule.exports = {
  // ブラウザ環境をシミュレート(React コンポーネントテスト用)
  testEnvironment: 'jsdom',

  // Node.js 環境(API テスト用)
  // testEnvironment: 'node',

  // テスト実行前に読み込むファイル
  setupFiles: [
    '<rootDir>/src/polyfills.js',
    '<rootDir>/src/env-setup.js',
  ],

  // テストフレームワーク設定後に読み込むファイル
  setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'],
};

環境別の設定例をご紹介します。

javascript// src/setupTests.js - React Testing Library の設定
import '@testing-library/jest-dom';
import { configure } from '@testing-library/react';

// テストの設定
configure({
  testIdAttribute: 'data-testid',
});

// グローバルなモック設定
global.ResizeObserver = jest
  .fn()
  .mockImplementation(() => ({
    observe: jest.fn(),
    unobserve: jest.fn(),
    disconnect: jest.fn(),
  }));

// ローカルストレージのモック
const localStorageMock = {
  getItem: jest.fn(),
  setItem: jest.fn(),
  removeItem: jest.fn(),
  clear: jest.fn(),
};
global.localStorage = localStorageMock;
javascript// src/env-setup.js - 環境変数の設定
process.env.NODE_ENV = 'test';
process.env.API_BASE_URL = 'http://localhost:3001';
process.env.MOCK_API = 'true';

モジュール解決の設定

モジュールの解決方法を設定することで、インポートパスの簡略化や外部ライブラリの取り扱いを制御できます。

moduleNameMapping と modulePaths

moduleNameMapping は、モジュール名のエイリアスを設定する重要な機能です。

javascriptmodule.exports = {
  // パスエイリアスの設定
  moduleNameMapping: {
    // @ を src ディレクトリのエイリアスとして使用
    '^@/(.*)$': '<rootDir>/src/$1',

    // コンポーネントディレクトリのエイリアス
    '^@components/(.*)$': '<rootDir>/src/components/$1',

    // ユーティリティディレクトリのエイリアス
    '^@utils/(.*)$': '<rootDir>/src/utils/$1',

    // CSS ファイルのモック
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',

    // 画像ファイルのモック
    '\\.(jpg|jpeg|png|gif|svg)$':
      '<rootDir>/src/__mocks__/fileMock.js',
  },

  // モジュール検索パス
  modulePaths: ['<rootDir>/src', '<rootDir>/node_modules'],
};

実際のファイル構造に合わせた設定例です。

javascript// プロジェクト構造
// src/
//   components/
//     Button/
//   hooks/
//   utils/
//   pages/

module.exports = {
  moduleNameMapping: {
    // 絶対パスでのインポートを可能にする
    '^@/(.*)$': '<rootDir>/src/$1',
    '^@components/(.*)$': '<rootDir>/src/components/$1',
    '^@hooks/(.*)$': '<rootDir>/src/hooks/$1',
    '^@utils/(.*)$': '<rootDir>/src/utils/$1',
    '^@pages/(.*)$': '<rootDir>/src/pages/$1',

    // テスト用のモック
    '^@test-utils$': '<rootDir>/src/test-utils',

    // 静的ファイルのモック
    '\\.(css|less|scss)$': 'identity-obj-proxy',
    '\\.(png|jpg|jpeg|gif|svg)$':
      '<rootDir>/src/__mocks__/fileMock.js',
  },
};
javascript// src/__mocks__/fileMock.js
module.exports = 'test-file-stub';

transform と transformIgnorePatterns

transform は、ファイルの変換方法を指定します。

javascriptmodule.exports = {
  // ファイル変換の設定
  transform: {
    // TypeScript ファイルの変換
    '^.+\\.(ts|tsx)$': 'ts-jest',

    // JavaScript ファイルの変換
    '^.+\\.(js|jsx)$': 'babel-jest',

    // CSS ファイルの変換
    '^.+\\.css$':
      '<rootDir>/src/transforms/cssTransform.js',
  },

  // 変換から除外するパターン
  transformIgnorePatterns: [
    '/node_modules/(?!(some-es6-package|another-package)/)',
    '\\.pnp\\.[^\\/]+$',
  ],
};

ES Modules を使用するライブラリを含む設定例です。

javascriptmodule.exports = {
  transform: {
    '^.+\\.(ts|tsx)$': [
      'ts-jest',
      {
        tsconfig: {
          jsx: 'react-jsx',
        },
      },
    ],
    '^.+\\.(js|jsx)$': [
      'babel-jest',
      {
        presets: [
          [
            '@babel/preset-env',
            { targets: { node: 'current' } },
          ],
          ['@babel/preset-react', { runtime: 'automatic' }],
        ],
      },
    ],
  },

  // ES Modules を使用するパッケージを変換対象に含める
  transformIgnorePatterns: [
    '/node_modules/(?!(uuid|nanoid|@testing-library/user-event)/)',
  ],
};
javascript// src/transforms/cssTransform.js
module.exports = {
  process() {
    return {
      code: 'module.exports = {};',
    };
  },
  getCacheKey() {
    return 'cssTransform';
  },
};

カバレッジ設定

コードカバレッジの計測は、テストの品質を評価する重要な指標です。

collectCoverage と coverageDirectory

javascriptmodule.exports = {
  // カバレッジ計測の有効化
  collectCoverage: true,

  // カバレッジレポートの出力先
  coverageDirectory: 'coverage',

  // カバレッジ計測対象のファイル
  collectCoverageFrom: [
    'src/**/*.{js,jsx,ts,tsx}',
    '!src/**/*.d.ts',
    '!src/index.tsx',
    '!src/reportWebVitals.ts',
    '!src/**/*.stories.{js,jsx,ts,tsx}',
    '!src/**/__tests__/**',
    '!src/**/*.test.{js,jsx,ts,tsx}',
  ],
};

詳細なカバレッジ設定の例です。

javascriptmodule.exports = {
  collectCoverage: process.env.CI === 'true',

  coverageDirectory: 'coverage',

  // カバレッジ計測対象の詳細指定
  collectCoverageFrom: [
    // 対象ファイル
    'src/**/*.{js,jsx,ts,tsx}',

    // 除外ファイル
    '!src/**/*.d.ts',
    '!src/index.tsx',
    '!src/serviceWorker.ts',
    '!src/reportWebVitals.ts',
    '!src/**/*.stories.{js,jsx,ts,tsx}',
    '!src/**/__tests__/**',
    '!src/**/*.test.{js,jsx,ts,tsx}',
    '!src/**/__mocks__/**',

    // 設定ファイルの除外
    '!src/**/config/**',
    '!src/**/constants/**',
  ],

  // カバレッジ計測から除外するパス
  coveragePathIgnorePatterns: [
    '/node_modules/',
    '/build/',
    '/coverage/',
    'src/types/',
    'src/assets/',
  ],
};

coverageThreshold と coverageReporters

カバレッジの閾値設定により、品質基準を維持できます。

javascriptmodule.exports = {
  // カバレッジレポートの形式
  coverageReporters: [
    'text', // コンソール出力
    'text-summary', // サマリー表示
    'html', // HTML レポート
    'lcov', // CI ツール連携用
    'json', // JSON 形式
  ],

  // カバレッジの最低基準
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80,
    },

    // 特定ディレクトリの基準
    './src/components/': {
      branches: 90,
      functions: 90,
      lines: 90,
      statements: 90,
    },

    // 特定ファイルの基準
    './src/utils/validation.ts': {
      branches: 100,
      functions: 100,
      lines: 100,
      statements: 100,
    },
  },
};

段階的なカバレッジ向上のための設定例です。

javascript// 段階的な品質向上設定
const isCI = process.env.CI === 'true';
const isProduction = process.env.NODE_ENV === 'production';

module.exports = {
  coverageReporters: [
    'text-summary',
    ...(isCI ? ['lcov'] : ['html']),
    ...(isProduction ? ['json'] : []),
  ],

  coverageThreshold: {
    global: {
      // 開発環境では緩い基準、CI では厳しい基準
      branches: isCI ? 85 : 70,
      functions: isCI ? 85 : 70,
      lines: isCI ? 85 : 70,
      statements: isCI ? 85 : 70,
    },

    // 新規開発コンポーネントは高い基準
    './src/components/new/': {
      branches: 95,
      functions: 95,
      lines: 95,
      statements: 95,
    },
  },
};

高度な設定オプション

プロジェクトの規模や要件に応じて、より高度な設定オプションを活用できます。

globals と preset

javascriptmodule.exports = {
  // グローバル変数の設定
  globals: {
    'ts-jest': {
      tsconfig: 'tsconfig.json',
      isolatedModules: true,
    },

    // カスタムグローバル変数
    __DEV__: true,
    __TEST__: true,
    __API_URL__: 'http://localhost:3001',
  },

  // プリセット設定
  preset: 'ts-jest',

  // または複数のプリセットを組み合わせ
  // preset: '@shelf/jest-mongodb'
};

TypeScript プロジェクト向けの詳細設定です。

javascriptmodule.exports = {
  preset: 'ts-jest',

  globals: {
    'ts-jest': {
      // TypeScript 設定ファイルの指定
      tsconfig: {
        jsx: 'react-jsx',
        esModuleInterop: true,
        allowSyntheticDefaultImports: true,
      },

      // 型チェックの無効化(高速化)
      isolatedModules: true,

      // Babel との併用
      babelConfig: true,
    },

    // 環境変数のモック
    process: {
      env: {
        NODE_ENV: 'test',
        REACT_APP_API_URL: 'http://localhost:3001',
      },
    },
  },
};

projects と watchPlugins

大規模プロジェクトでは、複数の設定を管理する必要があります。

javascriptmodule.exports = {
  // 複数プロジェクトの設定
  projects: [
    // フロントエンド用設定
    {
      displayName: 'Frontend',
      testMatch: ['<rootDir>/src/**/*.test.(js|ts|tsx)'],
      testEnvironment: 'jsdom',
      setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'],
    },

    // バックエンド用設定
    {
      displayName: 'Backend',
      testMatch: ['<rootDir>/server/**/*.test.(js|ts)'],
      testEnvironment: 'node',
      setupFilesAfterEnv: [
        '<rootDir>/server/setupTests.js',
      ],
    },

    // E2E テスト用設定
    {
      displayName: 'E2E',
      testMatch: ['<rootDir>/e2e/**/*.test.(js|ts)'],
      testEnvironment: 'node',
      runner: '@jest/runner',
    },
  ],

  // ウォッチモード用プラグイン
  watchPlugins: [
    'jest-watch-typeahead/filename',
    'jest-watch-typeahead/testname',
    'jest-watch-select-projects',
  ],
};

reporters の活用

テスト結果のレポート形式をカスタマイズできます。

javascriptmodule.exports = {
  // レポーターの設定
  reporters: [
    'default',

    // JUnit 形式のレポート(CI 用)
    [
      'jest-junit',
      {
        outputDirectory: 'test-results',
        outputName: 'junit.xml',
      },
    ],

    // HTML レポート
    [
      'jest-html-reporters',
      {
        publicPath: './test-report',
        filename: 'report.html',
        expand: true,
      },
    ],

    // Slack 通知
    [
      'jest-slack-reporter',
      {
        channel: '#dev-notifications',
        username: 'Jest Bot',
      },
    ],
  ],
};

実践的な設定例

実際のプロジェクトで使用できる、包括的な設定例をご紹介します。

React + TypeScript プロジェクト

javascript// jest.config.js - React + TypeScript 用設定
const path = require('path');

module.exports = {
  // 基本設定
  testEnvironment: 'jsdom',
  roots: ['<rootDir>/src'],

  // テストファイルの検索
  testMatch: [
    '<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}',
    '<rootDir>/src/**/*.(test|spec).{js,jsx,ts,tsx}',
  ],

  // セットアップファイル
  setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts'],

  // モジュール解決
  moduleNameMapping: {
    '^@/(.*)$': '<rootDir>/src/$1',
    '^@components/(.*)$': '<rootDir>/src/components/$1',
    '^@hooks/(.*)$': '<rootDir>/src/hooks/$1',
    '^@utils/(.*)$': '<rootDir>/src/utils/$1',
    '^@types/(.*)$': '<rootDir>/src/types/$1',

    // 静的ファイルのモック
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
    '\\.(png|jpg|jpeg|gif|svg)$':
      '<rootDir>/src/__mocks__/fileMock.js',
  },

  // ファイル変換
  transform: {
    '^.+\\.(ts|tsx)$': [
      'ts-jest',
      {
        tsconfig: 'tsconfig.json',
      },
    ],
    '^.+\\.(js|jsx)$': [
      'babel-jest',
      {
        presets: [
          [
            '@babel/preset-env',
            { targets: { node: 'current' } },
          ],
          ['@babel/preset-react', { runtime: 'automatic' }],
        ],
      },
    ],
  },

  // 変換除外
  transformIgnorePatterns: [
    '/node_modules/(?!(uuid|@testing-library/user-event)/)',
  ],

  // カバレッジ設定
  collectCoverage: process.env.CI === 'true',
  collectCoverageFrom: [
    'src/**/*.{js,jsx,ts,tsx}',
    '!src/**/*.d.ts',
    '!src/index.tsx',
    '!src/**/*.stories.{js,jsx,ts,tsx}',
    '!src/**/__tests__/**',
    '!src/**/*.test.{js,jsx,ts,tsx}',
  ],

  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80,
    },
  },

  // レポーター
  reporters: [
    'default',
    ...(process.env.CI
      ? [
          [
            'jest-junit',
            {
              outputDirectory: 'test-results',
              outputName: 'junit.xml',
            },
          ],
        ]
      : []),
  ],

  // ウォッチプラグイン
  watchPlugins: [
    'jest-watch-typeahead/filename',
    'jest-watch-typeahead/testname',
  ],
};

Node.js API プロジェクト

javascript// jest.config.js - Node.js API 用設定
module.exports = {
  // Node.js 環境
  testEnvironment: 'node',

  // テストファイルの検索
  testMatch: [
    '<rootDir>/src/**/__tests__/**/*.{js,ts}',
    '<rootDir>/src/**/*.(test|spec).{js,ts}',
    '<rootDir>/tests/**/*.{js,ts}',
  ],

  // セットアップ
  setupFilesAfterEnv: ['<rootDir>/tests/setup.js'],

  // モジュール解決
  moduleNameMapping: {
    '^@/(.*)$': '<rootDir>/src/$1',
    '^@controllers/(.*)$': '<rootDir>/src/controllers/$1',
    '^@services/(.*)$': '<rootDir>/src/services/$1',
    '^@models/(.*)$': '<rootDir>/src/models/$1',
    '^@utils/(.*)$': '<rootDir>/src/utils/$1',
  },

  // TypeScript 変換
  transform: {
    '^.+\\.ts$': 'ts-jest',
  },

  // グローバル設定
  globals: {
    'ts-jest': {
      tsconfig: 'tsconfig.json',
    },
  },

  // カバレッジ設定
  collectCoverageFrom: [
    'src/**/*.{js,ts}',
    '!src/**/*.d.ts',
    '!src/index.ts',
    '!src/server.ts',
    '!src/config/**',
    '!src/migrations/**',
  ],

  // テスト環境の設定
  testTimeout: 10000,

  // データベースのセットアップ・クリーンアップ
  globalSetup: '<rootDir>/tests/globalSetup.js',
  globalTeardown: '<rootDir>/tests/globalTeardown.js',
};

モノレポ環境

javascript// jest.config.js - モノレポ用設定
module.exports = {
  projects: [
    // Web アプリケーション
    {
      displayName: 'web',
      testMatch: [
        '<rootDir>/packages/web/**/*.test.(js|ts|tsx)',
      ],
      testEnvironment: 'jsdom',
      setupFilesAfterEnv: [
        '<rootDir>/packages/web/src/setupTests.ts',
      ],
      moduleNameMapping: {
        '^@/(.*)$': '<rootDir>/packages/web/src/$1',
      },
    },

    // API サーバー
    {
      displayName: 'api',
      testMatch: [
        '<rootDir>/packages/api/**/*.test.(js|ts)',
      ],
      testEnvironment: 'node',
      setupFilesAfterEnv: [
        '<rootDir>/packages/api/tests/setup.js',
      ],
      moduleNameMapping: {
        '^@/(.*)$': '<rootDir>/packages/api/src/$1',
      },
    },

    // 共通ライブラリ
    {
      displayName: 'shared',
      testMatch: [
        '<rootDir>/packages/shared/**/*.test.(js|ts)',
      ],
      testEnvironment: 'node',
      moduleNameMapping: {
        '^@/(.*)$': '<rootDir>/packages/shared/src/$1',
      },
    },
  ],

  // 共通設定
  collectCoverageFrom: [
    'packages/*/src/**/*.{js,ts,tsx}',
    '!packages/*/src/**/*.d.ts',
  ],

  coverageDirectory: 'coverage',

  watchPlugins: [
    'jest-watch-typeahead/filename',
    'jest-watch-typeahead/testname',
    'jest-watch-select-projects',
  ],
};

まとめ

Jest の設定ファイルは、テスト環境を最適化するための強力なツールです。本記事でご紹介した設定オプションを活用することで、以下のメリットを得られます。

主要なポイント

設定カテゴリ主要オプション効果
テスト実行testMatch, testEnvironmentテストファイルの検索とテスト環境の最適化
モジュール解決moduleNameMapping, transformインポートパスの簡略化と変換処理
カバレッジcollectCoverage, coverageThresholdコード品質の可視化と基準設定
高度な設定projects, reporters大規模プロジェクトへの対応

適切な設定により、開発効率の向上とテスト品質の確保を両立できます。プロジェクトの成長に合わせて設定を見直し、継続的に改善していくことが重要ですね。

設定ファイルの理解を深めることで、Jest をより効果的に活用し、信頼性の高いアプリケーション開発を実現していきましょう。

関連リンク