Reactでアプリケーション開発におけるユニットテストについて調べてみました。
ユニットテストはプログラムで記載した処理に対して与えた情報(引数など)に想定した通りの結果が返るかをプログラムでチェックします。処理を変えない限り結果が変わることがないのでリファクタリングなどで処理を変更しないなら既存のユニットテストは動作するはずで、動作しなければ記載した処理に間違いがあると直ぐに判明します。
手を加えたところは必ずテストするのが原則です。ユニットテストをソースをコミットする前に自動でテストを実行する仕組みにすれば、想定したテストすべてチェック出来て継続的な開発においてデグレーションを未然に防ぐことが出来ます。
React Create App
過去の記事でも公式ドキュメントに記載のReact Create Appを利用してきました。React Create Appをインストールするとユニットテストができる準備は既に終えています。詳細はReact Create Appの公式ドキュメントより「Running Tests」を参照して下さい。インストール直後で、サンプルのユニットテストとしてApp.test.tsxが存在します。npm run test
によりテストが実施されます。その状態でテストを変更して保存すると再びテストが実施されます。getByText
メソッドの値を変更して保存して確かめてみて下さい。変更を元に戻して保存したら変更されていないと判定されて余計なテスト実行がされない仕組みになっています。テスト対象のApp.tsxも同様に変更したタイミングでテストが走り、元に戻すとテストは実施されません。
開発しながらユニットテストを起動しておくと、ソースを保存したタイミングでテストが実行されるので間違いがあればすぐに気が付きます。
JestでESMのパッケージ読み込みエラーの対応
JEST公式ドキュメントに対応方法の記載があります。これを package.json
に記述します。axios
の呼び出しで Cannot use import statement outside a module.
と出力されました。このライブラリがESMパッケージのようなのでエラーが出ないようにします。こちらが対応したソースです。
当初は、エラーで出力されているURLを確認したり、ネットで調べたりして ts-jestでTypeScriptで記述されているソースに対応する必要があると言う記事があって調べていたのですが、トライ・アンド・エラーであれこれ試してもエラーが取れずに悩んでしまいました。
Create Script Appの初期インストールでサンプルとして入っているテストコードがTypeScriptなので、このライブラリはいるのだろうかと疑問がありました。結果的に今回の対応では不要でした。
さらに調べると、 jest.config.js
と package.json
にJestの設定を記述する2通りの記事に出会って、結果的に後者に記述してエラーが出なくなりました。解決方法を知っていれば5分で済むのに何日も足踏みしてしまって時間がもったいないですが仕方がないです。
React Testing Library
React Create Appの公式ドキュメントより「Running Tests」にはReact Testing Libraryに付いて記載があります。
公式ドキュメントのTesting LibraryにReact Testing Libraryのドキュメントがあります。
React Create Appがおすすめするライブラリのようです。エンドユーザが使うのと同じようにReactコンポーネントを操作できます。DOMノードを使ってクエリと呼ばれるメソッドでページ内の要素を見つけてイベントを発火したり値を取得出来ます。
簡単なテストを記述してみます
公式ドキュメントの実装例を参考にテストを記述してみます。
React Testing LibraryのQueries
数種類のQueriesメソッドを使ってコンポーネント内のDOM要素を取得します。
Queriesのタイプは、 getBy...
queryBy...
findBy...
と3種類あり要素が見つかるとき見つからないときなどで振る舞いが異なるようです。詳細は公式ドキュメントのテーブルを参照。
Queriesには優先度があって、ユーザー操作によってどう使われるかに似せるべきというガイダンスに基づき、使うメソッドを選ぶようです。 getByRole
は馴染みがなかったのですが、Accessible Rich Internet Applications (ARIA) というハンディキャップを持つ人々にとってよりアクセシブルにする方法を定義した物を使うようです。
ARIAの説明
WAI-ARIA ロール
コンポーネントをアクセシブルになるように設計しておくことが求められていると推測しています。
慣れないうちは、 getbyText
で要素を取得すれば大抵の要素は取れそうですが、優先度が高いメソッドを使うほうがあとあと都合が良いと思います。もう少し理解を深める必要がありそうです。
Testing Library公式の例を参考に、いくつかテストを記載して動作させたサンプルコードです。
サーバーからデータフェッチするテスト
サーバーからデータフェッチするテストをTypeScriptで書いてみました。一番良く使うパターンだと思われます。
MSW
MSWは、実際のリクエストをインターセプトするサービスワーカーAPIを使ったAPIモックライブラリーです。サーバーの実装が出来ていなくてもクライアントだけで完結するのでユニットテストだけでなく、開発時にも有益なライブラリだという印象です。
最後に
公式ドキュメントに記載の内容とサンプルを確認して実際に動作させることで理解が深まりました。
また、ドキュメントに記載の別ライブラリも利用することで簡単に記述できたり便利になります。Reactもそうですが、その技術だけを知っていてもダメで派生する技術も併せて利用して初めて実務で使えるようになります。目的のライブラリを使うために別のライブラリも学習が必要になるので使いこなせるまで相応の時間と努力が欠かせません。事前調査なしにライブラリの利用だけが決まっていると、関連するラーブラリーの調査もかさんで想像以上に時間を取られてしまうので気をつけたいですね。