【React】Jestの基本:Reactでテストを書く準備

JavaScript

こんにちは、かつコーチです。

前回までは認証・セキュリティ編として、Protected RouteやXSS対策を扱ってきました。

安全なアプリが作れるようになったら、次に意識したいのが「そのコードが本当に正しく動いているか」を保証する仕組みです。

ここからは数回に分けて、Reactアプリの「テスト」について解説していきます。

初回の今回は、テストの土台となるJestというテストフレームワークの基本を押さえていきましょう。

Jestとは?

JavaScript・TypeScript向けのテストフレームワーク

Jestは、Meta社が開発しているJavaScript・TypeScript向けのテストフレームワークです。

「関数に特定の値を渡したら、期待した結果が返ってくるか」を自動的に検証してくれるツールだと考えてください。

Create React AppやVite + Reactの構成でも広く採用されており、Reactのテストといえばまず名前が挙がる定番の選択肢です。

なぜテストを書く必要があるのか

「動いているんだから、わざわざテストを書かなくてもいいのでは?」と感じる人も多いと思います。

私自身、最初はそう思っていた一人でした。

しかし、実際に機能追加や修正を重ねていくと、「あるページを直したら、別のページが壊れていた」という経験を何度もすることになります。

テストコードがあれば、コードを変更したときに「今まで動いていた部分が壊れていないか」を自動的にチェックできます。

これを回帰テスト(デグレ防止)と呼び、開発が進むほどその価値を実感するようになります。

テストの種類

単体テスト・結合テスト・E2Eテストの違い

Reactアプリのテストには、大きく分けて次のような種類があります。

種類対象目的
単体テスト(ユニットテスト)関数・コンポーネント単体個々の処理が正しく動くか確認する
結合テスト複数のコンポーネントの組み合わせ連携部分が正しく動くか確認する
E2Eテストアプリ全体(実際のブラウザ操作)ユーザー視点で一連の操作が成立するか確認する

Jestは、このうち主に単体テスト・結合テストを担当するツールです。

E2Eテストについては、このシリーズの後半で別のツールを使って扱う予定なので、今はJestが「細かい単位のテストを担当する道具」だと理解しておけば十分です。

Jestの環境構築

インストール手順

Vite + React + TypeScriptのプロジェクトを前提に、必要なパッケージをインストールします。

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

TypeScriptのコードをそのままテストできるように、ts-jestも一緒に入れておきます。

設定ファイルの作成

jest.config.tsを作成し、TypeScript用の設定を記述します。

// jest.config.ts
import type { Config } from "jest";

const config: Config = {
  preset: "ts-jest",
  testEnvironment: "jsdom",
  testMatch: ["**/*.test.ts", "**/*.test.tsx"],
};

export default config;

ここでのポイントはtestEnvironment: "jsdom"です。

Reactのコンポーネントはブラウザ上のDOMを前提にしているため、Node.js環境だけではテストを実行できません。

jsdomは、Node.js上で疑似的にブラウザのDOM環境を再現してくれるライブラリで、これを指定することでコンポーネントのテストが可能になります。

package.jsonにスクリプトを追加

テストを毎回コマンドを打たずに実行できるよう、package.jsonにスクリプトを追加しておきます。

{
  "scripts": {
    "test": "jest"
  }
}

これでnpm testと打つだけでテストが実行できるようになります。

Jestの基本文法

describeとit(test)

Jestのテストコードは、describeit(もしくはtest)という2つの関数を軸に組み立てます。

// sum.test.ts
function sum(a: number, b: number): number {
  return a + b;
}

describe("sum関数", () => {
  it("2つの数値を足し算できる", () => {
    expect(sum(1, 2)).toBe(3);
  });

  it("マイナスの数値でも計算できる", () => {
    expect(sum(-1, -2)).toBe(-3);
  });
});

describeはテストのグループ(まとまり)を表し、itが個々のテストケースを表します。

expect(実際の値).toBe(期待する値)という形で、「この値はこうなるはずだ」というアサーション(検証)を書きます。

よく使うマッチャー

toBe以外にも、目的に応じてさまざまなマッチャー(検証方法)が用意されています。

test("よく使うマッチャーの例", () => {
  expect(1 + 1).toBe(2);                       // 完全一致
  expect({ name: "かつコーチ" }).toEqual({ name: "かつコーチ" }); // オブジェクトの中身が一致
  expect([1, 2, 3]).toContain(2);               // 配列に含まれるか
  expect(null).toBeNull();                      // nullかどうか
  expect(() => {
    throw new Error("エラー");
  }).toThrow();                                  // エラーが発生するか
});

toBeはプリミティブな値の比較に、toEqualはオブジェクトや配列の中身の比較に使う、という使い分けを覚えておくと迷いにくくなります。

つまずきやすいポイント:toBeとtoEqualの混同

オブジェクトの比較で失敗するケース

私が初めてJestに触れたとき、最初につまずいたのがこのtoBetoEqualの違いでした。

❌ Before:オブジェクトの比較にtoBeを使ってしまう

test("ユーザー情報オブジェクトの比較", () => {
  const user = { name: "かつコーチ", age: 30 };
  expect(user).toBe({ name: "かつコーチ", age: 30 });
  // テスト失敗:中身は同じでも別のオブジェクトとして扱われる
});

toBeObject.isと同じ比較方法を使うため、中身が同じでも参照先が異なる別のオブジェクトは「一致しない」と判定されます。

見た目は同じデータなのになぜかテストが落ちる、という状況に最初は戸惑いました。

✅ After:オブジェクトの比較にはtoEqualを使う

test("ユーザー情報オブジェクトの比較", () => {
  const user = { name: "かつコーチ", age: 30 };
  expect(user).toEqual({ name: "かつコーチ", age: 30 });
  // テスト成功:中身(プロパティの値)が一致していればOK
});

toEqualは値の中身を再帰的に比較してくれるため、オブジェクトや配列を検証するときはこちらを使うのが基本です。

「プリミティブ値ならtoBe、オブジェクトや配列ならtoEqual」というルールを覚えておくだけで、このつまずきは回避できます。

まとめ

この記事のポイント

  • JestはMeta社製のJavaScript・TypeScript向けテストフレームワーク
  • テストコードは、コードを変更したときの「デグレ防止」に役立つ
  • ReactコンポーネントのテストにはtestEnvironment: "jsdom"の設定が必要
  • describeでグループ化し、ittest)で個々の検証を書く
  • プリミティブ値の比較はtoBe、オブジェクトや配列の比較はtoEqualを使う

次に読むべき記事

Jestの基本文法が分かったところで、次はReactコンポーネントを実際にテストするための専用ライブラリ、React Testing Libraryについて学んでいきましょう。

→ 次の記事:React Testing Library入門

タイトルとURLをコピーしました