📝

フロントエンドのテストを書き始めました

2023/09/15に公開

ライフイズテック株式会社 サービス開発部の山口 (@no_clock) です。塾プロダクトグループでソフトウェアエンジニアをしています。

8 月からフロントエンドのテストを書き始めました。テストカバレッジで見ると、 1 ヶ月経ってようやく 25% を超えてきたところです[1]

フロントエンドのテスト経験は正直少ないのですが、セオリーやプロダクト特有の事情も踏まえつつ、どんな判断でどこから進めているのかを整理しました。何かの参考になれば幸いです。

※以下は React を前提とした話です。

プロダクト特有の事情から考える

  • これまでフロントエンドの品質担保は QA プロセス(手動)に依存していた(いわゆるアイスクリームコーン型)。
  • 生徒の学習状況や管理者の権限に応じた制御など、ロジックが複雑な箇所がある[2]
    • QA プロセスで相応数の不具合を発見している。
    • テストなしにリファクタリングするのは怖く、内部品質が下がるのを承知で微妙な修正をせざるを得ないことがある。
  • プロダクトとしては、生徒の学習機会を損なわないことが優先。
    • 「操作できない」「表示されない」などの学習機会を損なう不具合は最小限に留めたい。
    • 軽微なデザイン崩れなどは、優先順位をつけるとしたら後回しになる。

これらの事情を踏まえると、よし E2E テストだ! VRT (Visual Regression Testing) だ! とはなりにくいと思います。よって、初期段階では E2E テストや VRT は実施せず、ロジックのテストから書き始めていく判断をしました。

セオリーも踏まえて考える

テストの粒度や割合については、テストピラミッドやテスティングトロフィーと呼ばれる概念があります。

プロダクトの事情を鑑みつつこれらの概念に当てはめると、次のようなテストから書き始めるのが良いと判断しました。

  • テストサイズ: Small テスト(テストピラミッドの最下部)
    • ロジックのテストには、ネットワークや DB アクセスは必要ない。高速で安定して実行できると嬉しい。
  • トロフィーでの区分: なるべく Integration テスト
    • Unit テストは実装の詳細に依存しやすいため(例えばコンポーネント分割の単位が変わっただけで壊れてしまう)。
    • 上記の懸念がなく妥当と思われる場合は Unit テストでもよい。

ライブラリとしては、 Jest と React Testing Library を選んでいます。

その他の工夫

大雑把な判断は記載した通りですが、継続的に質の良いテストを書き続けられるよう、細かな工夫(こだわり)もあります。

モックは API レスポンスだけ

モックすると「そのモックが正しいか」を考える必要が出てきてしまい、何かと面倒なことになります。そのため、モックは極力使っていません。

ただし、ネットワークアクセスを避けるため Mock Service Worker (MSW) を用いた API レスポンスのモックだけは許容しています。

ちなみに「古典派」に分類されるようです。

https://twitter.com/t_wada/status/1448864195357777928

実装しつつテストを増やす

開発をストップするのではなく、開発を継続しながら、手を入れた付近のテストを少しずつ増やしています。

変更頻度が高い箇所(テストが欲しい箇所)ほどテストが充実していきます。

逃げない

中には、どうしてもテストが書きにくいコンポーネントもあります。テストを書かずに済ませたり、先にコンポーネントを書き直したい衝動に駆られることがあります。

ただ、テストが書きにくいコンポーネントほどテストが欲しいものです。書きます。

品質を維持しつつ、開発を加速させる

まだまだテストカバレッジは低く、検証できている範囲もわずかです。しかしながら、リファクタリングを実施できたり、開発時にテストが失敗して不具合に早く気づけたりと、既に効果が出始めています。

今後も品質を維持しながら開発を加速させていけるよう、取り組んでいきます。


ちょっと宣伝

ライフイズテック サービス開発部では、気軽にご参加いただけるカジュアルなイベントを実施しています。開催予定のイベントは、 connpass のグループからご確認ください。興味のあるイベントがあったらぜひ参加登録をお願いいたします。皆さんのご参加をお待ちしています!

脚注
  1. C1: 分岐網羅では 18% ↩︎

  2. 権限制御はサーバーサイドでも行っています。念のため ↩︎

Discussion