Jestで始める単体テスト

2025/01/22に公開

テストをしない理由

  • テストに対する不確信(本当に必要か?)
  • 面倒くさい
  • 時間がかかる
  • 企画が頻繁に変わる
  • SIで保守まで行わない場合

テストをする理由

  • 過去に発生したエラーが再発する場合
  • コードが複雑で、頻繁かつ多くの修正が必要な場合
  • 1つのコードを修正したら、他の部分でエラーが発生する場合

TDDは必要か?
フロントエンドではBDDが現実的な選択となる場合がある。
会社の状況に応じて実現可能な方法を選択。

テストの種類

  • ユニットテスト(レンガ)
  • 統合テスト(壁)
  • E2Eテスト

インストール

npm i jest -D
npm init jest@latest

npx jest

-Dを使うことで開発モードでインストールする。
テストはプロジェクトの本番配布には含まれないため、開発用として扱う。

next、reactの場合は

npm install --save-dev jest @testing-library/react @testing-library/jest-dom @testing-library/user-event
  • jest: テストランナー。
  • @testing-library/react: Reactコンポーネントをテストするためのライブラリ。
  • @testing-library/jest-dom: DOM関連のマッチャー(例: toBeInTheDocument など)を提供。
  • @testing-library/user-event: ユーザーイベントをシミュレーションするためのライブラリ。
  • ts-jest: TypeScript環境でJestを使用できるようにサポートするツール。

テストの原則

テストが一度失敗することを確認する必要がある。
時々、どんな値を入れても成功するケースがあるため、特に非同期処理(Promise)が絡む場合にはdoneやreturnの記述が重要となる。

失敗(赤)を確認してから成功(緑)を見ること。

middlewares/index.js
exports.isLoggedIn = (req, res, next) => {
  if (req.isAuthenticated()) {
    next();
  } else {
    res.status(403).send("ログインが必要");
  }
};

exports.isNotLoggedIn = (req, res, next) => {
  if (!req.isAuthenticated()) {
    next();
  } else {
    const message = encodeURIComponent("ログインした状態");
    res.redirect(`/?error=${message}`);
  }
};

ログインしている場合

middlewares/index.spec.js
describe("isLoggedIn", () => {
  // テストの説明文には具体的な実装に依存せず、抽象的な内容を記述する
  test("ログインしている場合", () => {
    // 企画の意図を反映する
    // モックオブジェクトを作成
    const req = {
      isAuthenticated() {
        // ログインしている場合は true を返す
        return true;
      },
    };
    const res = {};
    const next = jest.fn(); // nextが呼ばれたかを確認するためのモック関数
    isLoggedIn(req, res, next);
    expect(next).toHaveBeenCalledTimes(1); // mock関数が一回CALLされたか確認
  });
});

ログインしてない場合

middlewares/index.spec.js
describe("isNotLoggedIn", () => {
  test("ログインしてなかったら ", () => {
    const req = {
      isAuthenticated() {
        // ログインしてなかったらfalseを返す
        return false;
      },
    };
    const res = {};
    const next = jest.fn();
    isNotLoggedIn(req, res, next);
    expect(next).toHaveBeenCalledTimes(1);
  });
});
});

テストカバレッジ


Uncovered Line #sでテストされていない行を確認できる。
理想は100%だが、難しい場合は90%を目指す。ただし、カバレッジが100%だからといってエラーが発生しないわけではない。

Bizlink Developers Blog

Discussion