T-CREATOR

ESLint × Vitest/Playwright:テスト環境のグローバルと型を正しく設定

ESLint × Vitest/Playwright:テスト環境のグローバルと型を正しく設定

テストコードを書く際に「describe is not defined」「test が見つかりません」といったエラーに遭遇したことはありませんか?

Vitest や Playwright のようなテストフレームワークでは、グローバル関数や変数が暗黙的に提供されますが、ESLint や TypeScript がこれらを認識できないために、コードは正常に動作するのにエディタ上でエラー表示が消えないという状況が発生します。

本記事では、ESLint と TypeScript における Vitest および Playwright のグローバル環境設定と型定義の正しい構成方法を、実例を交えて徹底解説いたします。

背景

テストフレームワークとグローバル API

Vitest や Playwright といったモダンなテストフレームワークは、テストコードの記述を簡潔にするため、グローバルスコープに多くの関数や変数を自動的に注入します。

以下はテストフレームワークが提供する代表的なグローバル関数です。

#フレームワークグローバル関数・変数の例
1Vitestdescribe, test, it, expect, vi, beforeEach, afterEach
2Playwrighttest, expect, page, context, browser
3Jestdescribe, test, it, expect, jest, beforeAll, afterAll

これらの関数は実行時には問題なく動作しますが、静的解析ツールである ESLint や TypeScript はデフォルトではこれらのグローバル変数を認識できません。

ESLint と TypeScript の静的解析

ESLint と TypeScript は、コードの品質と型安全性を保つために静的解析を行います。

以下の図は、テストコード作成時の静的解析の流れを示したものです。

mermaidflowchart TD
  code["テストコード<br/>(*.test.ts)"] -->|解析| eslint["ESLint"]
  code -->|型チェック| tsc["TypeScript<br/>Compiler"]
  eslint -->|グローバル未定義| err1["no-undef エラー"]
  tsc -->|型情報なし| err2["型エラー"]
  err1 & err2 --> problem["エディタに<br/>エラー表示"]

図のポイント:

  • テストコードは実行時に正常動作するが、静的解析時にエラーが発生する
  • ESLint は未定義のグローバル変数を検出し、TypeScript は型情報の欠如を指摘する

設定不足によって発生する問題

適切な設定がない場合、以下のような問題が発生します。

#問題の種類具体的な症状影響
1ESLint エラー'describe' is not defined (no-undef)エディタに赤波線が表示される
2TypeScript エラーCannot find name 'test' (TS2304)型チェックが失敗し、ビルドエラーになる
3IntelliSense 未動作自動補完が効かない開発効率が低下する
4CI での失敗Lint チェックが通らないデプロイがブロックされる

これらの問題を解決するには、ESLint の環境設定と TypeScript の型定義を正しく構成する必要があります。

課題

ESLint における課題

ESLint は、未定義のグローバル変数を参照すると no-undef ルールによってエラーを報告します。

以下は、Vitest のテストコードにおける典型的なエラー例です。

typescript// src/utils/math.test.ts

describe('Math utilities', () => {
  // ❌ ESLint Error: 'describe' is not defined (no-undef)

  test('should add two numbers', () => {
    // ❌ ESLint Error: 'test' is not defined (no-undef)

    expect(1 + 1).toBe(2);
    // ❌ ESLint Error: 'expect' is not defined (no-undef)
  });
});

これらのエラーは、ESLint がテストフレームワークのグローバル環境を認識していないために発生するものです。

TypeScript における課題

TypeScript は型情報を元にコードを解析しますが、テストフレームワークのグローバル関数の型定義が読み込まれていないと型エラーが発生します。

typescript// src/components/Button.test.ts

describe('Button component', () => {
  // ❌ TypeScript Error: Cannot find name 'describe'. TS2304

  it('should render correctly', () => {
    // ❌ TypeScript Error: Cannot find name 'it'. TS2304

    const result = expect(true).toBe(true);
    // ❌ TypeScript Error: Cannot find name 'expect'. TS2304
  });
});

このエラーを解決するには、TypeScript に対してテストフレームワークの型定義を明示的に読み込ませる必要があります。

Playwright 固有の課題

Playwright は、テストファイル内で pagecontext といった Fixture を暗黙的に提供しますが、これらも ESLint と TypeScript に認識させる必要があります。

typescript// e2e/login.spec.ts

test('user can login', async ({ page }) => {
  // ❌ ESLint Error: 'test' is not defined (no-undef)
  // ❌ TypeScript Error: Cannot find name 'test'. TS2304

  await page.goto('/login');
  // TypeScript は page の型を認識できない
});

以下は、課題をまとめた図解です。

mermaidflowchart LR
  testCode["テストコード"] --> eslintCheck["ESLint 解析"]
  testCode --> tsCheck["TypeScript<br/>型チェック"]

  eslintCheck -->|環境未設定| eslintErr["no-undef<br/>エラー"]
  tsCheck -->|型定義未導入| tsErr["TS2304<br/>エラー"]

  eslintErr --> devExp["開発体験<br/>の低下"]
  tsErr --> devExp

図のまとめ:

  • 環境設定と型定義の両方が不足している場合、ESLint と TypeScript の両方でエラーが発生する
  • これらのエラーは開発体験を著しく低下させる要因となる

解決策

Vitest の ESLint 環境設定

Vitest のグローバル API を ESLint に認識させるには、eslint-plugin-vitest を使用します。

プラグインのインストール

bashyarn add -D eslint-plugin-vitest

このプラグインは、Vitest 専用のルールと環境設定を提供します。

ESLint Flat Config での設定

ESLint 9.x 以降の Flat Config 形式での設定例です。

javascript// eslint.config.js
import vitest from 'eslint-plugin-vitest';

上記では、Vitest プラグインをインポートしています。

javascriptexport default [
  {
    files: ['**/*.test.ts', '**/*.spec.ts'],
    plugins: {
      vitest,
    },
    rules: {
      ...vitest.configs.recommended.rules,
    },
    languageOptions: {
      globals: {
        ...vitest.environments.env.globals,
      },
    },
  },
];

この設定では、以下のポイントを押さえています。

#設定項目役割
1filesテストファイルのみに適用する
2pluginsVitest プラグインを登録
3rulesVitest 推奨ルールを適用
4languageOptions.globalsVitest のグローバル変数を定義

レガシー Config での設定

ESLint 8.x 以前の .eslintrc.js 形式での設定例です。

javascript// .eslintrc.js
module.exports = {
  overrides: [
    {
      files: ['**/*.test.ts', '**/*.spec.ts'],
      extends: ['plugin:vitest/recommended'],
      env: {
        'vitest/env': true,
      },
    },
  ],
};

この設定により、テストファイル内で describetestexpect などのグローバル関数が認識されるようになります。

Vitest の TypeScript 型設定

Vitest のグローバル API を TypeScript に認識させるには、tsconfig.json で型定義を読み込む必要があります。

グローバル API モードの有効化

まず、Vitest 側でグローバル API モードを有効にします。

typescript// vitest.config.ts
import { defineConfig } from 'vitest/config';

設定ファイルの型定義をインポートします。

typescriptexport default defineConfig({
  test: {
    globals: true,
  },
});

globals: true を設定することで、グローバル API が有効になります。

TypeScript での型定義読み込み

次に、tsconfig.json で Vitest の型定義を読み込みます。

json{
  "compilerOptions": {
    "types": ["vitest/globals"]
  }
}

この設定により、describetestexpectvi などの型が自動的に利用可能になります。

複数の環境に対応する場合

テスト用とアプリケーション用で異なる型定義を使用する場合は、tsconfig を分離します。

json// tsconfig.test.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "types": ["vitest/globals"]
  },
  "include": ["**/*.test.ts", "**/*.spec.ts"]
}

アプリケーションコードとテストコードで型定義を明確に分離することで、型の競合を防げます。

Playwright の ESLint 環境設定

Playwright のグローバル API を ESLint に認識させるには、eslint-plugin-playwright を使用します。

プラグインのインストール

bashyarn add -D eslint-plugin-playwright

このプラグインは、Playwright 専用のルールと環境設定を提供します。

Flat Config での設定

javascript// eslint.config.js
import playwright from 'eslint-plugin-playwright';

Playwright プラグインをインポートします。

javascriptexport default [
  {
    files: ['e2e/**/*.spec.ts', 'tests/**/*.spec.ts'],
    ...playwright.configs['flat/recommended'],
  },
];

この設定では、E2E テストファイルに対して Playwright の推奨設定を適用しています。

レガシー Config での設定

javascript// .eslintrc.js
module.exports = {
  overrides: [
    {
      files: ['e2e/**/*.spec.ts'],
      extends: ['plugin:playwright/recommended'],
    },
  ],
};

この設定により、testexpectpage などのグローバル変数が認識されます。

Playwright の TypeScript 型設定

Playwright の型定義を TypeScript に認識させる設定です。

Playwright 型定義の読み込み

json{
  "compilerOptions": {
    "types": ["@playwright/test"]
  }
}

この設定により、Playwright のテスト API とフィクスチャの型が利用可能になります。

E2E テスト専用の tsconfig

E2E テスト用に独立した tsconfig を作成する方法です。

json// e2e/tsconfig.json
{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "types": ["@playwright/test"]
  },
  "include": ["**/*.spec.ts"]
}

これにより、E2E テストコードとアプリケーションコードの型定義を完全に分離できます。

以下は、解決策の全体像を示す図です。

mermaidflowchart TB
  subgraph eslintConfig["ESLint 設定"]
    plugin["プラグイン<br/>インストール"]
    flatConfig["eslint.config.js<br/>で環境設定"]
  end

  subgraph tsConfig["TypeScript 設定"]
    vitestConfig["vitest.config.ts<br/>globals: true"]
    tsConfigTypes["tsconfig.json<br/>types 指定"]
  end

  plugin --> flatConfig
  vitestConfig --> tsConfigTypes

  flatConfig --> resolved["グローバル認識<br/>完了"]
  tsConfigTypes --> resolved

  resolved --> noError["エラー解消<br/>快適な開発"]

図で理解できる要点:

  • ESLint と TypeScript の両方で設定が必要
  • プラグインと型定義を組み合わせることで完全な認識が可能になる

具体例

Vitest の完全設定例

ここでは、Vitest を使用したプロジェクトの完全な設定例を示します。

ディレクトリ構造

textproject/
├── src/
│   ├── utils/
│   │   ├── math.ts
│   │   └── math.test.ts
│   └── components/
│       ├── Button.tsx
│       └── Button.test.tsx
├── vitest.config.ts
├── tsconfig.json
├── eslint.config.js
└── package.json

この構造では、テストファイルをソースコードと同じディレクトリに配置しています。

Vitest 設定ファイル

typescript// vitest.config.ts
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';

必要なプラグインをインポートします。

typescriptexport default defineConfig({
  plugins: [react()],
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: './src/test/setup.ts',
  },
});

主な設定項目の説明:

#設定項目説明
1globals: trueグローバル API を有効化
2environment: 'jsdom'DOM 環境をシミュレート
3setupFilesテスト実行前の初期化処理

ESLint 設定(Flat Config)

javascript// eslint.config.js
import js from '@eslint/js';
import typescript from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import vitest from 'eslint-plugin-vitest';

必要なプラグインとパーサーをインポートします。

javascriptexport default [
  js.configs.recommended,

  // TypeScript ファイル用の基本設定
  {
    files: ['**/*.ts', '**/*.tsx'],
    languageOptions: {
      parser: tsParser,
      parserOptions: {
        project: './tsconfig.json',
      },
    },
    plugins: {
      '@typescript-eslint': typescript,
    },
    rules: {
      ...typescript.configs.recommended.rules,
    },
  },

TypeScript ファイル全般に適用される基本設定です。

javascript  // テストファイル専用の設定
  {
    files: ['**/*.test.ts', '**/*.test.tsx'],
    plugins: {
      vitest,
    },
    rules: {
      ...vitest.configs.recommended.rules,
    },
    languageOptions: {
      globals: {
        ...vitest.environments.env.globals,
      },
    },
  },
];

テストファイルにのみ Vitest の環境とルールを適用します。

TypeScript 設定

json{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "jsx": "react-jsx",
    "strict": true,
    "moduleResolution": "bundler",
    "types": ["vitest/globals"]
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

重要なポイント:

#設定項目役割
1types: ["vitest​/​globals"]Vitest のグローバル型を読み込む
2lib: ["DOM"]DOM 型定義を含める
3strict: true厳格な型チェックを有効化

テストコード例

typescript// src/utils/math.test.ts

describe('Math utilities', () => {
  // ✅ 'describe' が正しく認識される

  test('should add two numbers correctly', () => {
    // ✅ 'test' と 'expect' が型安全に使える
    const result = 1 + 1;
    expect(result).toBe(2);
  });

  test('should multiply two numbers correctly', () => {
    const result = 3 * 4;
    expect(result).toBe(12);
  });
});

この設定により、ESLint エラーも TypeScript エラーも発生せず、自動補完も正常に動作します。

Playwright の完全設定例

次に、Playwright を使用した E2E テストの完全な設定例を示します。

ディレクトリ構造

textproject/
├── src/
│   └── pages/
│       └── index.tsx
├── e2e/
│   ├── login.spec.ts
│   ├── navigation.spec.ts
│   └── tsconfig.json
├── playwright.config.ts
├── tsconfig.json
├── eslint.config.js
└── package.json

E2E テストは専用のディレクトリに分離しています。

Playwright 設定ファイル

typescript// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

Playwright の設定に必要な関数と定義をインポートします。

typescriptexport default defineConfig({
  testDir: './e2e',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,

  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
  },

  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
  ],
});

主な設定項目:

#設定項目説明
1testDirテストファイルの場所
2fullyParallelテストの並列実行
3baseURLテスト対象の URL
4projectsテスト対象のブラウザ

ESLint 設定(Flat Config)

javascript// eslint.config.js
import js from '@eslint/js';
import typescript from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import playwright from 'eslint-plugin-playwright';

Playwright プラグインを含む必要なモジュールをインポートします。

javascriptexport default [
  js.configs.recommended,

  // TypeScript 基本設定
  {
    files: ['**/*.ts'],
    languageOptions: {
      parser: tsParser,
    },
    plugins: {
      '@typescript-eslint': typescript,
    },
    rules: {
      ...typescript.configs.recommended.rules,
    },
  },

TypeScript ファイル全般の基本設定です。

javascript  // E2E テスト専用の設定
  {
    files: ['e2e/**/*.spec.ts'],
    ...playwright.configs['flat/recommended'],
  },
];

E2E テストファイルに Playwright の推奨設定を適用します。

E2E テスト用 TypeScript 設定

json// e2e/tsconfig.json
{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "types": ["@playwright/test"],
    "moduleResolution": "bundler"
  },
  "include": ["**/*.spec.ts"]
}

E2E テスト専用の型定義を読み込みます。

E2E テストコード例

typescript// e2e/login.spec.ts
import { test, expect } from '@playwright/test';

明示的にインポートする方法(推奨)です。

typescripttest('user can login with valid credentials', async ({
  page,
}) => {
  // ✅ 'test'、'page'、'expect' が正しく認識される

  await page.goto('/login');

  await page.fill(
    'input[name="email"]',
    'user@example.com'
  );
  await page.fill('input[name="password"]', 'password123');

  await page.click('button[type="submit"]');

  await expect(page).toHaveURL('/dashboard');
});

この設定により、Playwright の Fixture(pagecontext など)が型安全に利用できます。

以下は、設定の適用範囲を示す図です。

mermaidflowchart TB
  subgraph testFiles["テストファイル"]
    vitest["src/**/*.test.ts<br/>(Vitest)"]
    pw["e2e/**/*.spec.ts<br/>(Playwright)"]
  end

  subgraph configs["設定ファイル"]
    eslintConfig["eslint.config.js"]
    vitestConfig["vitest.config.ts"]
    pwConfig["playwright.config.ts"]
    tsMain["tsconfig.json"]
    tsE2E["e2e/tsconfig.json"]
  end

  vitest -->|適用| eslintConfig
  vitest -->|適用| vitestConfig
  vitest -->|適用| tsMain

  pw -->|適用| eslintConfig
  pw -->|適用| pwConfig
  pw -->|適用| tsE2E

  eslintConfig --> result["型安全で<br/>エラーのない<br/>テストコード"]
  vitestConfig --> result
  pwConfig --> result
  tsMain --> result
  tsE2E --> result

図で理解できる要点:

  • テストファイルの種類によって適用される設定が異なる
  • ESLint、TypeScript、テストフレームワークの設定が連携して動作する
  • 各設定ファイルが適切に構成されることで、快適な開発環境が実現できる

複数のテストフレームワークを共存させる場合

プロジェクトによっては、Vitest と Playwright を同時に使用するケースがあります。

ESLint での共存設定

javascript// eslint.config.js
import vitest from 'eslint-plugin-vitest';
import playwright from 'eslint-plugin-playwright';

export default [
  // Vitest 用の設定
  {
    files: ['src/**/*.test.ts', 'src/**/*.spec.ts'],
    plugins: { vitest },
    rules: { ...vitest.configs.recommended.rules },
    languageOptions: {
      globals: { ...vitest.environments.env.globals },
    },
  },

  // Playwright 用の設定
  {
    files: ['e2e/**/*.spec.ts'],
    ...playwright.configs['flat/recommended'],
  },
];

ファイルパターンを明確に分けることで、それぞれのテストフレームワークに適した設定を適用できます。

TypeScript での共存設定

json// tsconfig.json(メイン)
{
  "compilerOptions": {
    "types": ["vitest/globals"]
  },
  "include": ["src/**/*"],
  "exclude": ["e2e"]
}

メインの設定では Vitest の型のみを読み込みます。

json// e2e/tsconfig.json(E2E テスト用)
{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "types": ["@playwright/test"]
  },
  "include": ["**/*.spec.ts"]
}

E2E テスト用の設定では Playwright の型を読み込みます。

この設計により、型の競合を防ぎつつ、両方のテストフレームワークを快適に使用できます。

まとめ

本記事では、ESLint と TypeScript において Vitest および Playwright のグローバル環境と型を正しく設定する方法を解説しました。

重要なポイントをまとめます。

#項目設定内容
1ESLint専用プラグインをインストールし、グローバル環境を設定
2TypeScripttsconfig.jsontypes でフレームワークの型定義を指定
3ファイル分離テストの種類ごとに設定を分けることで型の競合を防ぐ
4Flat ConfigESLint 9.x 以降では Flat Config 形式を使用

これらの設定を適切に行うことで、以下のメリットが得られます。

  • no-undef や TypeScript の型エラーが解消される
  • エディタの自動補完と IntelliSense が正常に機能する
  • CI での Lint チェックがスムーズに通過する
  • 開発体験が大幅に向上し、生産性が高まる

テストコードを書く際には、実行時の動作だけでなく、静的解析ツールとの連携も重要です。

本記事で紹介した設定方法を参考に、快適なテスト環境を構築していただければ幸いです。

関連リンク