TypeScriptプロジェクトをJestでテストする方法

# はじめに
先日、業務でJestを用いてTypeScriptのコードをテストする機会がありました。
私のようにJestを初めて扱う方が、よりスムーズに導入を行えるよう手順をまとめました。

# Jestとは
JavaScript/TypeScrptのテストフレームワークです。
最小限の設定ですぐにテストを行えるのが特徴です。

# Jest + TypeScriptの導入手順
それでは、導入手順を見ていきましょう。
## 1. パッケージのインストール
初めに、パッケージマネージャー（ここではnpm）を使って必要なパッケージをインストールします。

```
npm install --save-dev jest ts-jest @types/jest
```

JavaScriptだけであれば、jestのみのインストールでテストを行うことができますが、TypeScriptのテストには`ts-jest @types/jest`も必要です。

- `jest`：Jest本体です
- `ts-jest`：TypeScriptで書いたテストコードを、JavaScriptにトランスパイルすることなく実行できるようにするものです
- `@types/jest`：Jestに、TypeScriptの型情報を付与するものです。これにより、テストコードの型チェックを行えるようになります

## 2. Jest設定ファイルの生成
続いて、TypeScriptのテストコードを実行できるように設定を行います。
`ts-jest`をインストールしただけではTypeScriptをテストできず、設定を行う必要があります。
以下のコマンドを実行すると、`jest.config.js`が生成されます。

```
npx ts-jest config:init
```

```javascript: jest.config.js
/** @type {import('ts-jest').JestConfigWithTsJest} **/
module.exports = {
  preset: "ts-jest",
  testEnvironment: "node",
};
```
- `@type`から始まるコメント：エディターに型情報を与えるためのもので、エディター上で入力補完が効くようになります
- `preset: 'ts-jest'`：Jestを、`ts-jest`をベースとして実行するようにする設定です

## 3. package.jsonのscripts設定
テストの実行は`npx jest`（または`node_modules/.bin/jest`）で行うことができますが、`package.json`で以下を設定し、簡便に利用できるようにするのが一般的です。
```json
"scripts": {
  "test": "jest"
}
```
これにより、`npm (run) test`でテストが実行できるようになります。

# コード例
それでは、導入したJestを利用する手順も見ていきましょう。

## テスト対象コード
初めに、テスト対象のコードを用意します。
今回は、引数の名前が3文字以上20文字以下であれば有効とみなす、バリデーションロジックとしました。

```typescript: validateUsername.ts
export function isValidUsername(name: string): boolean {
  return name.length >= 3 && name.length <= 20;
}
```

## テストコード
続いてテストコードを作成しますが、ファイル名は`*.spec.ts` または `*.test.ts` である必要があります。

```typescript: validateUsername.spec.ts
import { isValidUsername } from './validateUsername';

describe('isValidUsername', () => {
  test('3文字以上20文字以下ならtrue', () => {
    expect(isValidUsername('user123')).toBe(true);
  });

  test('2文字以下ならfalse', () => {
    expect(isValidUsername('ab')).toBe(false);
  });

  test('21文字以上ならfalse', () => {
    expect(isValidUsername('a'.repeat(21))).toBe(false);
  });
});
```
Jestには様々なメソッドが用意されていますが、最低限、以下を使用すればテストが可能です。
- `test(name, fn, timeout)`(または`it(name, fn, timeout)`)
    - 1つ1つのテストケースを定義します
        - name: 項目名
        - fn: テスト関数
        - timeout(optional): テスト失敗と判断するまでの待ち時間
- `describe(name, fn)`
    - テストケースのグループ化を行います
        - name: 項目名
        - fn: テスト関数
- `expect(value)`
    - テストケースの結果を記述します
- `toBe(value)`
    - 結果の期待値を記述します

# テスト実行・結果
[3. package.jsonのscripts設定](#3.-package.jsonのscripts設定) で設定した`npm run test`を実行すると、以下のような結果が出力されます。

**ファイル内の全てのテストが成功した場合**

![スクリーンショット 2025-04-30 12.14.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3795697/45c836c2-8842-435a-9fbe-0bcb41c3c82c.png)

**1つでも失敗のケースがある場合**

![スクリーンショット 2025-04-30 12.16.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3795697/c6cebf98-ee3e-4fe8-9c15-2eb1e9024cec.png)

- **PASS/FAIL `./index.spec.ts`**: 成功/失敗・テスト対象のファイル名
- **`isValidUsername`以下**: `describe`・`test`で記述した項目名
    - 失敗の場合
        - Expected: 期待値
        - Received: 実際の結果の値
        - 失敗箇所の明示
- **Test Suites**: （失敗ファイル数、）成功ファイル数、全ファイル数
- **Tests**: （失敗項目数、）成功項目数、全項目数
- **Snapshots**: 保存した、ある時点の出力（オブジェクトやコンポーネントのレンダリング結果など）の数。次回のテスト実行時に差分を検出してテストに利用する仕組みですが、今回は扱いません
- **Time**: テストにかかった時間

# おわりに
以上の手順によって、TypeScriptコードをJestでテストできるようになります。
この記事が、どなたかの助けになれば幸いです。


# 参考文献
https://jestjs.io/ja/

https://typescriptbook.jp/tutorials/jest