React Native 開発でも mocha を使う理由
React Native ではテスティングフレームワークとして Jest が推奨されていますが、 Jest は Jasmine 系の API を受け継いでいることもあり、 mocha に比べると習熟が難しいことが難点です。 API を覚えるまでは expect
に続けてどういった条件を書けるんだっけ、とリファレンスをあさる必要が出てきます。
こういったことを覚えずにすむ mocha は非常にコストパフォーマンスのよい技術です。単純に assert
で満たすべき条件を羅列してやるだけでテストが書けます。テスト駆動開発で有名な @t_wada 和田卓人さんは No API is the best API
とおっしゃっています。
ちなみに react-native init
時の Jest インストールは設定で抑制できます。
React コンポーネントテスト用ライブラリー enzyme
React コンポーネントをレンダリングしてどういった仮想 DOM に展開されるかをエミュレートしてくれる enzyme というライブラリーがあります。基本は 1 段だけ展開する shallow
を使うのですが、フルレンダリングすることもできます。
展開された仮想 DOM の構造が想定したものかどうか、というテストを書くわけです。ただし、実は enzyme もいろいろな API を持っています。
これではせっかく mocha を選んだ意味がないじゃないかと思うかもしれませんが、基本的に使うのは特定の仮想 DOM が含まれているかを確かめる contains
と CSS セレクターで DOM を探すことのできる find
およびテキストノードを取り出す text
ていどで用がたります。
そもそもテストを書くべきコンポーネントというのが少ないと考えています。 React の思想に則って dumb なコンポーネント設計をしているのであれば、 props に対して決まりきった仮想 DOM を出力するコンポーネントがたくさん、それらを条件によって使い分けるコンポーネントが少数という構成になるはずです。個人的に後者のみにテストを書けば良いと考えています。なので、特定の条件を満たす props を入力としたときに、想定する仮想 DOM もしくはテキストノードを含むかどうかのチェックのみで済むことが多いのです。
ちなみに JavaScript フロントエンドを長く経験されている方はお気づきかと思いますが、 enzyme の API は古き良き jQuery ととても似ています。これは既存知識を使いまわせるため、テスティングライブラリーとしては筋の良い設計だと思いますが、 jQuery を知らない方々に使ってもらうにあたってはこういったことはまったく意味がありません。
サンプル
mocha + enzyme で React Native 用にテストを書いたリポジトリーを次に用意しています。
注意点として次が挙げられます。
- enzyme で React Native コンポーネントをレンダリングするために
react-native-mock
が必要 -
.ios.js
や.android.js
をうまくハンドリングできるようにPLATFORM
という環境変数で切り分けている
まとめ
React コンポーネントだけのテストであれば Jest の toMatchSnapshot
のみを使うという割り切りでもいいのですが、それ以外のロジックのテストを書くことを考えると mocha + enzyme という選択肢がコスパがよいと考えています。
今回は React Native にフォーカスしてのハナシでしたが、もちろん React で開発する際も mocha + enzyme は大安定です。ぜひ試してみてください。