ReactTestingLibraryの導入と使い方・Jestとの違い【完全版】
この記事のポイント
React Testing Libraryは内部実装に依存しないユーザー視点のテストツールであり、ViteやJestを用いた環境構築からscreenやuser-eventによるDOM検証、非同期制御、CI連携を通じた保守性の高い開発を実現する実践的な検証手法です。
React Testing Libraryの使い方がわからず、非同期処理や操作シミュレーションの書き方で困っていませんか。メンテナンス性が高く、依存関係の変更に強いテスト設計を身につけて、開発効率を高めたいと考える方は多いはずです。
こうした疑問にお答えします。
本記事の内容
- React Testing Libraryの導入手順とJestやViteでの環境構築
- 基本APIやuser-eventを用いたテストの実装方法
- 子要素の取得やact関数の扱いなど実務的な運用ポイント
React Testing Libraryを活用すれば、内部実装に依存しないユーザー目線の堅牢なテストコードを効率的に記述できます。TypeScript環境での設定方法や、GitHub上のリポジトリを参考にした設計、npmでのインストール手順まで幅広く解説。
本質的な設計思想を理解することで、エラーに強い高品質なコンポーネント開発が可能になります。さっそく見ていきましょう。
React Testing Libraryの概要
React Testing Libraryは、Reactとは何かを踏まえた上で導入する、Reactコンポーネントをテストするための軽量なライブラリです。DOM Testing Libraryを基盤としており、ユーザーが実際にアプリを操作する感覚に近い形でテストを記述できます。
フロントエンド開発向けのテストライブラリ
React Testing Libraryは、現代のフロントエンド開発においてデファクトスタンダードとなっているツールです。作成したコンポーネントがブラウザ上でどのように振る舞うかを、効率よく検証することに特化しています。
主な特徴は、render関数でコンポーネントを描画し、screenオブジェクトを介して要素を取得する点です。基本的なテスト手順は以下の通りとなります。
- render関数でコンポーネントを仮想DOMにレンダリングする
- screen.getByTextなどで特定の要素を検索する
- expect関数を用いて要素の存在や状態を評価する
npmを使用してプロジェクトへ導入すれば、複雑な内部構造を意識せずにテストを行えます。結果としてコードの可読性が高まり、メンテナンスも容易になるはずです。
テストランナー「Jest」との違い
React Testing Libraryを導入する際、よく混同されるのがJestというツールです。両者の違いは明確であり、組み合わせて使用するのが一般的な手法となります。
| 項目 | React Testing Library | Jest |
|---|---|---|
| 分類 | テストユーティリティ | テストランナー |
| 主な役割 | DOM操作やUI要素の検索 | テストの実行と合否判定 |
| 具体的な機能 | renderやscreen | describeやexpect |
React Testing Libraryは「テストの内容」を担当し、Jestは「テストの実行環境」を提供する役割を担います。
ユーザー操作を重視した設計思想
このライブラリの哲学は、テストをソフトウェアの実際の使用方法に近づけることです。コンポーネントの内部実装に依存せず、ユーザーが画面上で見るものに基づいてテストを書くべきだという考え方が根底にあり、React Hooksのテスト方法 を扱う場合も同じ原則が適用されます。
この設計思想により、以下のメリットを享受できます。
- リファクタリングへの耐性:内部コードを書き換えてもユーザーから見た挙動が変わらなければテストは成功し続けます。
- アクセシビリティの向上:役割で検索するgetByRoleなどを使うことで、支援技術に配慮したコードになります。
子要素を確認する場合も、まずgetByRoleなどの推奨クエリを活用しましょう。どうしても特定の要素を指定できない場合にのみ、テスト専用のIDを検討してください。
テストカバレッジを維持する戦略
品質の高いアプリケーションを維持するには、適切なテストカバレッジの確保が不可欠です。ViteやTypeScript環境でも、主要なユーザー操作を網羅する戦略が求められます。
具体的な戦略は以下の通りです。
- user-eventの使用:クリックやキー入力などの操作を忠実に再現して画面の変化を検証する
- act関数の理解:レンダリングや更新が完了するまで適切に待機し、警告を回避する
- デバッグの活用:screen.debugでDOMの状態を出力しつつ、エラーの原因を特定する
API通信などの非同期処理が含まれる場合は、findByクエリやwaitFor関数を利用してください。これらの手法を駆使することで、GitHub上のプロジェクトなどでも信頼性の高いテストコードを共有できます。
React Testing Libraryの導入手順
React Testing Libraryは、ユーザーの視点でReactコンポーネントをテストするためのツールです。内部の実装ではなく、実際のDOM操作やアクセシビリティに基づいたテストを推奨しています。
このライブラリを使うと、メンテナンスしやすく変更に強いコードを記述可能です。特にReact Testing LibraryとTypeScriptを組み合わせた開発は、現代のフロントエンドにおいて標準的なスキルといえます。
① ViteでReactプロジェクトを作成する
開発環境の基盤として、高速なビルドツールであるViteを使用します。現在のReact開発において、ViteでReactの環境構築 は最も標準的な選択肢の一つです。
TypeScript環境のプロジェクトを立ち上げるには、以下の手順を実行してください。
- ターミナルで
npm create vite@latest [プロジェクト名] -- --template react-tsを実行する - 作成されたディレクトリに移動して
npm installで依存関係をインストールする
Viteのテンプレートにはテスト環境が含まれていないため、手動で構成する必要があります。Vite環境へReact Testing Libraryを導入する際は、Jestなどのテストランナーを別途設定しましょう。
② npmで関連パッケージを追加する
テストの実行に必要なパッケージをnpm経由でインストールします。React Testing Library本体に加えて、テストランナーのJestや仮想DOM環境などのライブラリが必要です。
以下のコマンドをターミナルで実行して、必要なツールを追加してください。
npm install --save-dev jest @types/jest ts-jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom @testing-library/user-event
主要なパッケージの役割を以下の表にまとめました。
| パッケージ名 | 役割 |
|---|---|
| jest / ts-jest | テストを実行するエンジンとTypeScriptへの対応を行う |
| jest-environment-jsdom | ブラウザの挙動をNode.js上でシミュレートする環境 |
| @testing-library/react | コンポーネントをレンダリングし、DOMを操作するコア機能 |
| @testing-library/jest-dom | 要素の存在確認など便利なカスタムマッチャーを提供 |
| @testing-library/user-event | クリックや入力などのユーザー操作を忠実に再現する |
③ テスト用の初期設定ファイルを作成する
インストールが完了したら、JestがTypeScriptやReact Testing Libraryを認識できるように設定します。まず、プロジェクトのルートディレクトリに jest.config.ts を作成してください。
export default {
preset: 'ts-jest',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
};
次に、カスタムマッチャーを自動で読み込むための jest.setup.ts を作成します。ファイル内には import '@testing-library/jest-dom'; と記述してください。
最後に package.json の scripts に "test": "jest" を追加します。これで npm test コマンドを使って、いつでも簡単にテストを実行できるようになります。
④ TypeScriptの型定義を設定する
React TypeScript環境 でReact Testing Library独自の拡張機能を認識できるように設定を調整します。設定を怠ると toBeInTheDocument などのメソッドで型エラーが発生するため注意が必要です。
プロジェクトの tsconfig.json を開き、以下のように編集してください。
{
"compilerOptions": {
"esModuleInterop": true,
"types": ["@testing-library/jest-dom", "@types/jest"]
}
}
この設定により、GitHubなどにある公式サンプルと同様の型補完が有効になります。Jestのグローバル変数も適切に定義され、型安全な環境でテストコードを記述可能です。
以上のステップで、React Testing Libraryを用いた確かなテスト環境が整いました。コンポーネントの品質を担保しながら、自信を持って開発を進めることができます。
React Testing Libraryを使ったテストの実装方法
React Testing Libraryは、ユーザーが実際にアプリケーションを操作する方法に近い形でコンポーネントをテストするためのライブラリです。内部の実装詳細に依存せずアクセシビリティに基づいたテストを推奨しており、リファクタリングに強いコードを作成できます。
ここではReact Testing Library導入後の主要機能である要素取得やユーザー操作、非同期処理の制御について具体的に解説します。ViteやTypeScript環境での利用を想定した実用的な手法を見ていきましょう。
screenオブジェクトで画面の要素を取得する
画面上の要素を取得する際は、screenオブジェクトを利用することが標準的です。これによりrender関数からの分割代入を省き、簡潔に要素へアクセスできるようになります。
React Testing Libraryでは、アクセシビリティに基づいたクエリの使用が推奨されています。主要なクエリの種類と特徴を以下にまとめました。
| クエリの種類 | 取得の優先順位 | 主な用途 |
|---|---|---|
| getByRole | 最優先 | ボタンやヘッダーなどアクセシビリティロールで指定 |
| getByLabelText | 高 | フォームのラベルに関連付けられた入力項目を指定 |
| getByText | 中 | 画面上に表示されている特定の文字列を指定 |
| getByTestId | 低 | data-testid属性を直接指定する最終手段 |
要素の取得はまずrender関数でコンポーネントをレンダリングし、次にscreenオブジェクトから適切なクエリを呼び出します。最後にexpect関数とマッチャーを組み合わせて、期待通りの要素が存在するか検証してください。
例えばボタンを取得する場合は、screen.getByRole('button', { name: '送信' })のように記述します。UIとしての役割で要素を特定するため、HTML構造の変化に強いテストになります。
userEventで画面操作を再現する
ユーザーのクリックや入力をシミュレートするには、user-eventライブラリを使用してください。fireEventよりも実際のブラウザ挙動に近いuserEventの使用が現在は推奨されています。
userEventを使用する際は、まずsetup関数を呼び出してユーザーインスタンスを初期化します。操作の完了を待機するために、async/awaitを用いた非同期処理の記述が必要です。
- setup関数でインスタンスを生成し、操作の準備を整える
- await user.click(要素) のようにアクションを実行する
- 操作後のDOM変化をscreenクエリで確認する
fireEventはDOMイベントを即時に発火させるだけですが、userEventはフォーカス移動などの副次的な挙動まで再現します。これにより、より信頼性の高いテストが可能になります。
act関数で非同期処理を制御する
act関数は、ステート更新がテスト内で適切に処理されることを保証する仕組みです。現在は多くのAPI内部で自動的にラップされているため、開発者が直接記述する機会は減っています。
複雑な非同期処理を伴う場合は、userEventの操作が内部でactを使用しているため明示的なラップは不要です。非同期で現れる要素を待つ場合は、findBy系のクエリを活用しましょう。
findByRoleなどのクエリは、要素が出現するまで一定時間ポーリングを行います。これにより、API通信後に表示されるメッセージなどもスマートにテストできます。
手動でactを呼び出すよりも、findByクエリをawaitして待機する方法が最新のベストプラクティスです。簡潔なコードで、非同期レンダリングを正確にテストできます。
コンポーネント内の子要素を判定する
Reactコンポーネント設計 で分割した子要素を判定するには、jest-domのマッチャーを組み合わせて利用します。特定のテキストが含まれているか、あるいは期待した子が描画されているかを確認しましょう。
子要素の判定には、要素の存在を確認するtoBeInTheDocumentや内容を検証するtoHaveTextContentがよく使われます。複数の項目を一括取得する場合は、getAllByRoleが便利です。
リスト形式をテストする場合、まずgetAllByRoleで全要素を取得し、配列の長さが期待通りか確認します。その上で各要素のテキスト内容が正しいかをチェックしてください。
クラス名などの実装詳細ではなく、ユーザーが実際に目にする情報を基準に子要素を検証する視点が、メンテナンス性の高いテスト作成に繋がります。
API通信をモック化する
外部API通信を含む場合は、実際のサーバーにリクエストを送らず、モックを使用してレスポンスを制御します。ネットワーク環境に依存せず、高速にテストを実行できるメリットがあります。
APIモックの手法には、主に以下の2つのアプローチが存在します。
| 手法 | 特徴 |
|---|---|
| Jest Mock | axiosなどのライブラリを直接モック化する手軽な方法 |
| MSW | ネットワークレベルでリクエストを補足する推奨手法 |
Jestを用いる場合は、まずjest.mockでモジュールをモック化し、mockResolvedValueOnceでテストデータを定義します。その後にコンポーネントを実行し、データが正しく表示されるか検証しましょう。
最近はGitHubなどのプロジェクトでも、より現実的な通信を再現できるMSWの利用が増えています。MSWはプロダクトコードの変更を最小限に抑えられるため、規模に応じて適切な手法を選んでください。
React Testing Libraryを実務で運用するポイント
React Testing Library(RTL)は、コンポーネントの内部実装ではなく、ユーザーの操作視点でテストを行うライブラリです。DOMの状態検証に特化しており、アクセシビリティクエリを使うことで壊れにくいテストを実現します。
実務でReact Testing Libraryを導入する際は、文法だけでなく保守性を意識した設計が重要です。効率的な環境構築にはnpmを用いたインストールから始めましょう。
保守性を下げるアンチパターンを避ける
RTLのテストでは、実装の細部に依存した記述を避けることが最も大切です。コードの内部構造を変えただけでテストが失敗すると、保守コストが増大してしまいます。
避けるべき記述と推奨される方法を以下の表にまとめました。
| 項目 | アンチパターン | 推奨される方法 |
|---|---|---|
| 要素の取得 | data-testid の多用 | getByRole や getByText |
| 状態の検証 | state や props を直接確認 | 表示テキストやボタンの活性状態を確認 |
| 非同期の待機 | 固定時間の sleep | findBy クエリや waitFor の使用 |
TypeScript環境でReact Testing Libraryを活用すれば、型安全にクエリを利用できます。特にgetByRoleを優先すると、支援技術を利用するユーザーと同じ視点で要素を特定可能です。
E2Eテストツールと役割を分ける
テスト戦略を立てる際は、React Testing LibraryとJestの組み合わせによるユニットテストと、E2Eツールの役割を明確に分けます。RTLがUIの振る舞いを検証し、JestがテストのCI実行環境を提供する点が両者の核心的な違いです。
- React Testing Libraryが担う領域
- コンポーネント単体や複数のコンポーネントが組む振る舞いの検証
- ユーザー操作に伴うDOM変化の確認
- JSDOM環境での高速な実行
- E2Eテストツールが担う領域
- 実際のブラウザを用いたシステム全体のフロー検証
- ページ遷移やクロスブラウザの動作確認
- ネットワーク遅延やインフラ層を含む結合確認
RTLは実行速度に優れているため、網羅的なロジック検証に最適です。画面遷移後の挙動などはPlaywrightなどのE2Eテストに任せると、全体のバランスが整います。
Next.jsやViteの環境で検証する
Next.jsのApp Router環境でも、React Testing Libraryはクライアントコンポーネントのテストで中心的な役割を担います。SPA構成でReact Routerのテスト を行う場合や、Viteを利用する場合も、renderやscreenなどの基本APIは共通して使用可能です。
- クライアントコンポーネント: 従来のrender手法でそのままテストを実行できます。
- サーバーコンポーネント: 非同期関数として定義されるため、モック化などの工夫が必要です。
環境ごとの差異は、jest.setup.jsやvitest.setup.tsなどのセットアップファイルに集約されます。子要素を取得する際も、環境に依存せず一貫したクエリを利用できるのが強みです。
Reduxの状態管理を検証する
Reduxを使用している場合は、Providerを含めたレンダリングを行うカスタムレンダーを作成しましょう。act関数を適切に扱うことで、状態更新に伴う再レンダリングを正しく処理できます。
- テストごとに状態をリセットするテスト専用Storeを作成する
- render関数をラップしてProviderで囲むユーティリティを用意する
- user-eventでアクションを発火させ、DOMの変化を確認する
内部のdispatchが呼ばれたかではなく、画面上の数値が変化したかをscreen.getByTextで検証してください。これが、実装に依存しないRTLらしいテスト手法といえます。
GitHub ActionsでCIに組み込む
品質を維持するために、GitHubリポジトリと連携してCI環境でテストを自動実行しましょう。通常はJestやVitestなどのテストランナーを経由して、コマンドラインから実行します。
CI環境での標準的な手順は以下の通りです。
- npm ciで@testing-library/reactなどの依存関係をインストールする
- npm testコマンドでウォッチモードをオフにして実行する
- テスト失敗時にプルリクエストのビルドを失敗させる設定を行う
CI環境では自動的にウォッチモードが終了するように設定を確認してください。これにより、不具合を含むコードのマージを防ぎ、常に信頼性の高いコードベースを維持できます。
まとめ:React Testing Libraryで壊れにくいテストを実現しよう
本記事ではReact Testing Libraryの基本概念や、ViteやJestを用いた具体的な導入手順、実務で役立つテストの実装方法を解説しました。ユーザー目線のテストを重視する設計思想を理解し、TypeScript環境などで適切に活用することが大切です。
screenオブジェクトやact関数、user-eventを使いこなすことで、内部構造の変更に強いメンテナンス性の高いコードが書けます。子要素の取得方法や環境構築のコツを掴めば、npm経由でのインストール後もスムーズに開発を進められるはずです。
本記事のポイント
- React Testing Libraryは、実装詳細ではなくユーザー操作を基準としたテスト設計を推奨している
- Vite環境などへの導入からAPIのモック化、非同期処理の制御まで実務的な手法が豊富にある
- アンチパターンを回避してCI/CDへ組み込むことで、長期的なプロジェクトの品質維持に貢献できる
正しくツールを活用することで、リファクタリング時に壊れにくい堅牢なテストスイートを構築できます。開発効率とプロダクトの信頼性を大幅に向上させ、より良いフロントエンド開発を目指しましょう。
高品質な開発を実現するためのテスト戦略や、具体的な導入支援についてご相談がある方はお気軽にお問い合わせください。専門のスタッフがお客様のプロジェクトに最適な解決策を提案します。
参考文献
執筆者
編集部
Next.jsやAIを活用したモダンWeb開発・SEO実装に関する情報を発信。SEOに最適化したモダンWebサイト制作、設計ノウハウ、構造化データや内部リンク設計などを中心に扱っています。
監修者
MT Templates 代表/編集長
海外メディア企業でSEOエディターとして従事後、独立。複数メディア運営の経験をもとに、Next.jsやAIを活用したWeb開発・SEO技術を発信。リード獲得につながるサイト構築からSEO設計まで一貫したサポートを提供している。
関連記事
Reactのライフサイクルの仕組みとuseEffectでの実装【図解】
旧機能の廃止や再描画に悩む方へ、Reactのライフサイクルを図解し、useEffect等のフックによるアンマウント制御を学ぶことで、最適な実装が可能です。
Reactのコンポーネントの作り方・分け方・設計【初心者向け】
Reactのコンポーネントの適切な分け方や作り方に悩む方へ、種類や使い方、設計、ライブラリまで解説し、実務で活きる高保守性コード習得を導きます。
ReactのUIライブラリ人気7選・要件別の徹底比較【プロ解説】
UI開発に悩む方へ、人気のReactのUIライブラリを解説し、Material UI等の活用で技術的負債を防ぎ、美しいUIデザインによる保守性の高い開発を実現します。
useMemoの使い方・使わない基準とは?useCallbackとの違い
ReactでuseMemoの用途にお悩みですか。useCallbackやuseEffectとの違い、使わない基準を解説。不要な再レンダリングを防ぎ、アプリを最適化できます。
ReactとRedux入門・Toolkitの全5つの実装手順【初心者向け】
ReactでReduxを導入したい方向けに、ToolkitやTypeScriptでの実装手順から使わない条件まで解説し、実務的な状態管理スキルが身につく入門記事です。
ReactのContextの使い方とアンチパターン【プロが徹底解説】
ReactのContextでPropsバケツリレーを解消する使い方を解説。再レンダリングのアンチパターンやReduxとの比較を通じ、保守性の高い実装が可能です。