Vite × TypeScriptでJestテスト環境を構築する方法：envファイル対応まで徹底解説！

# はじめに
タイトルの通り、Vite環境でTypeScriptを用いた場合のテスト環境（Jest×Testing Library）の構築方法について記事にします！
まずは最低限のテスト環境を構築後、envファイルから情報を取得するための設定を追加してテストを実行する方法をご紹介いたします。

# 手順
- **1.Vite環境作成**
まずは以下のコマンドでVite環境を作成します。
コマンド実行時に環境を質問されるので、ReactとTypeScriptを選択します。
```console:Vite環境作成
npm create vite
```
- **2.App.tsxを編集（任意）**
初期状態でも良いのですが、とりあえずテストを通すため、App.tsxを編集します。
```tsx:App.tsx
function App() {
  return (
    <>
      <p>Vite</p>
    </>
  );
}

export default App;
```
- **3.パッケージのインストール**
テスト実行に必要な依存関係のインストールを行います。
```console:テスト環境導入
npm install --save-dev jest ts-jest @types/jest jest-environment-jsdom@latest @testing-library/react@latest @testing-library/jest-dom@latest @testing-library/user-event@latest  
```
- **4.設定ファイルを編集**
jestのテストを実行するための設定ファイルを追加します。
```js:jest.config.js
export default {
  preset: 'ts-jest',
  testEnvironment: 'jest-environment-jsdom',
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
};
```
:::note info
jest.config.js：JavaScriptテスティングフレームワークであるJestの設定ファイル。
- **preset: 'ts-jest'**
TypeScriptで書かれたコードをテストするためのプリセットを指定しています。ts-jestは、JestとTypeScriptを統合するためのパッケージです。
- **testEnvironment: 'jest-environment-jsdom'**
テスト環境としてjsdomを使用することを指定しています。jsdomは、Node.js上で動作する軽量なブラウザ環境を提供します。これにより、ブラウザ特有のAPI（例えば、documentやwindow）をテストで使用することができます。
- **moduleNameMapper**
モジュールのパスをエイリアスとしてマッピングするための設定です。ここでは、@/というエイリアスを<rootDir>/src/にマッピングしています。例えば、@/components/Buttonというインポートは、<rootDir>/src/components/Buttonに解決されます。

:::
```diff_json:package.json(中略)
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "lint": "eslint .",
    "preview": "vite preview",
+    "test": "jest"
  }
```
:::note info
- package.json：Node.jsプロジェクトの設定ファイル。
"scripts"セクションにある"test"スクリプトは、プロジェクトのテストを実行するためのコマンドを定義しています。具体的には、"jest"コマンドを実行します。
:::

```diff_json:tsconfig.json
{
  "files": [],
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" }
  ],
+  "compilerOptions": {
+    "esModuleInterop": true,
+    "jsx": "react-jsx"
+  }
}
```
:::note info
tsconfig.jsonファイル：TypeScriptコンパイラの設定を定義するためのファイル。
- **compilerOptions**
TypeScriptコンパイラの動作を制御するためのオプションを指定します。ここでは、以下の2つのオプションが設定されています：
    - **esModuleInterop**
CommonJSモジュールとESモジュールの互換性を向上させるための設定です。これにより、import文を使用してCommonJSモジュールをインポートする際の互換性が向上します。
    - **jsx**
JSXコードのコンパイル方法を指定します。ここでは、react-jsxが指定されており、これはReact 17以降の新しいJSX変換方式を使用することを意味します。この設定により、JSXコードがReactの新しい変換方式に従ってコンパイルされます。
:::
- **5.テストクラスの作成**
ここまで出来ましたらsrc直下に以下のファイルを作成します。
```tsx:App.test.tsx
import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";
import App from "./App";

/*
 * サンプルテスト
 */
describe("サンプルテスト", () => {
  test("[正常系]サンプルテスト", async () => {
    // 実行
    render(<App />);

    // 検証
    expect(screen.getByText("Vite")).toBeInTheDocument();
  });
});
```
- **6.テストクラス実行**
「4.設定ファイルを編集」で追加したコマンドを実行し、テストが疎通するかどうか確認します。
```console:jest実行
npm run test
```
```console:実行結果
 PASS  src/App.test.tsx
  サンプルテスト
    ✓ [正常系]サンプルテスト (12 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.061 s
Ran all test suites.
```

無事通ったようですね。
これにて最低限のテスト環境の構築は完了です。

- **7.環境変数読込のためのパッケージをインストール**
さて、次は.envから環境変数を取得するためのテスト環境を構築していきます。
まず、Viteは環境変数から値を取得するための方法が用意されているのですが、
その方法をそのまま使用するとテスト実行に失敗してしまいます（詳細は<a href="https://qiita.com/diskszk/items/ed6362e35e15f2fd790e">こちら</a>）
したがって、テスト実行時にもエラーとならないためのパッケージをインストールします↓。

```console:依存関係導入
npm i vite-plugin-env-compatible
```
:::note info
vite-plugin-env-compatibleは、Viteプロジェクトで環境変数をより簡単に扱うためのプラグインです。
Vite環境ではprocessオブジェクトが存在せず、process.envを通じた環境変数の取得が出来ないため、このパッケージを使ってproessオブジェクトを通じた環境変数の取得が出来るようにします。
:::


- **8.設定ファイルの変更**
追加したパッケージを利用するための設定ファイルの変更を行います。

```diff_typescript:vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
+import env from "vite-plugin-env-compatible";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react(),
+            env({ prefix: "VITE", mountedPath: "process.env" })],
});

```

- **9..envファイルの追加とApp.tsxの編集**
では、テスト実行時に環境変数を取得できるかを確認するため、.envファイルを追加し、App.tsxを以下の通り編集します。

```:.env
VITE_SECRET_KEY=SECRET_KEY_VALUE
```
```diff_tsx:App.tsx
function App() {
  return (
    <>
+      <p>Vite:{process.env.VITE_SECRET_KEY}</p>
    </>
  );
}

export default App;
```
:::note alert
.envファイルを追加した場合、必ず「.gitignore」ファイルに.envを追加してください！
（.gitignoreファイルに定義を追加せずGitHub等にpushすると、リモートリポジトリから機密情報が丸見えになります。）
:::
- **10.テストクラスの変更**
では、環境変数が取得できているかを確認するため、App.test.tsxクラスを変更してみましょう。

```diff_tsx:App.test.tsx
import "@testing-library/jest-dom";
+import { render, screen, waitFor } from "@testing-library/react";
import App from "./App";

/*
 * サンプルテスト
 */
describe("サンプルテスト", () => {
  test("[正常系]サンプルテスト", async () => {
    // 実行
    render(<App />);

    // 検証
+    waitFor(() => {
+      expect(screen.getByText("Vite:SECRET_KEY_VALUE")).toBeInTheDocument();
+    });
  });
});
```
- **11.テスト再実行**
さて、では環境変数が取得できているかのテストを実行してみましょう。
```console:jest実行
npm run test
```
```console:実行結果
 PASS  src/App.test.tsx
  サンプルテスト
    ✓ [正常系]サンプルテスト (14 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.121 s
Ran all test suites.
```

**<font color="red">ｷﾀ━━━━(ﾟ∀ﾟ)━━━━!!</font>**

これにてテスト環境の構築は完了です。
これで環境変数の取得も問題なしですね！

# おわりに
設定ファイルなどはあまり考えずおまじない的に追加しがちですが、
`"なんでこの設定が必要なのか"`ということを意識することで、予期せぬエラーが発生した際も対応出来る場合があります。
こういった細かいところの設定の意味なども考えながら実装していくことを意識してみましょう！

# 参考

https://zenn.dev/zhenyou620/articles/25d6f5810a7881



## JISOUのメンバー募集中🔥
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
気になる方はぜひHPからライン登録お願いします！👇

https://projisou.jp/