なぜUIコンポーネントテストは難しいのか

UIコンポーネントテストを書く行為は後回しになりやすい。それは難しさが要因に含まれているからと考えられる。 どのような部分が難しいのだろうか。

セットアップが難しいから

UIコンポーネントを動かすためにはブラウザ環境を擬似的に再現する必要がある。このこと自体はテストライブラリが実行してくれる。 問題はその後で、「実際にUIコンポーネントが動作する状況を追加で作り出す」のが難しい。ここで折れてしまいやすい。

例えば、ダークモード(背景が暗い色)とライトモード(背景が明るい色)の2つを切り替えられるアプリケーションがあったとする。 モードの状態管理がグローバルステート管理ライブラリの実装に依存しているとする。

すると、UIコンポーネントAがグローバルステートを参照して動作が変わる場合、テストするためにはUIコンポーネント・グローバルステートの初期状態を準備しなければならない。 選定したライブラリによっては、グローバルステートのモックアップ例が見つからない場合がある。 このような場面では手も足も出ず、テストを諦めてしまうことが起こりやすい。

他にも国際化対応(internationalization:通称i18n)ライブラリ・UIライブラリを使ったUIコンポーネントテストでつまづきやすい。 APIのレスポンスパラメータを受け取ってテストを書く場合も同様で、モックのセットアップ・モックの呼び出しでつまづきやすい。

例えUIコンポーネントテストを始めようと考えても、動かす前の段階で挫けてしまう罠が多いのである。

UIコンポーネント動作を再現するのが難しいから

UIコンポーネントテストは「コンポーネントを操作した」状況を作り出さないと意図した結果が得られないことがある。例えば、「ボタンをクリックしたときにテキストが変わる」ことをテストしたい場合は「ボタンをクリックした」状態をモックしなければならない。

これがテストフレームワークや利用しているライブラリごとに異なる。結果、書き方が分からず挫折してしまいやすい。 記載方法が書いてあったとしても、自分が置かれている状況に適用できるのかまで判断しなければならない点が難しさを増す要因となっている。

失敗の原因を探るのが難しいから

単体テストは入力に対して出力をテストする。つまり、テストが失敗している場合は入力(与えた引数や初期状態)または出力(関数やクラスの処理結果)、どちらから間違っていると予想できる。入力が意図通りかどうかは見直しやすいため、大半の場合は関数やクラスの処理に問題があると予想しやすい。

しかし、コンポーネントテストはこうはいかない。前述した通り、「UIコンポーネントが動作する状況を作り」、「ユーザーの操作を再現して」、「UIコンポーネントの処理を実行する」。この時点でテストの失敗要因を絞り込む対象は3つある。さらに動作状況や操作の再現の回数分、デバッグ対象の数は増える。自分の意図通り設定できているかはテストを実行してみないと分からない。

例えテストを実行できたとしても成功させられるとは限らない。UIコンポーネント自体に問題がないがテストに失敗する場合もある。デバッグの難しさによってだんだんとUIコンポーネントテストがメンテナンスできず、書くのを諦めてしまいやすい。