天の月

ソフトウェア開発をしていく上での悩み, 考えたこと, 学びを書いてきます(たまに関係ない雑記も)

Frontendのテスト全部知る 〜Unit TestからE2Eまで〜 - Encraft #18に参加してきた

knowledgework.connpass.com

こちらのイベントに参加してきたので、会の様子と感想を書いていこうと思います。

会の概要

以下、イベントページから引用です。

フロントエンドのテスト、書いてますか?

何を目的にテストを書くのか、どこまで書いたらいいのか、どう書くのがいいのかなどなど、フロントエンドのテストに関する悩みは色々とあるかと思います。

今回はフロントエンドのリアーキテクト文脈でのテストの話や、デグレを起こさないためのテストといった観点に焦点を当てながら、Unit TestからE2Eテストまで、広い範囲でお話しします。

会の様子

コンポーネントのテストとして採れそうな手法と、その効果を考える

最初にnus3さんからコンポーネントテストの話がありました。

Vitest, Playwright, Storybook, WebdriverIO, Cypress, Safetestを使用してそれぞれのライブラリでテストを書いてみたそうで、それぞれの特徴の説明がありました。

  • Vitest...設定を切り替えるだけで同じテストを別の動作環境で実行できる
  • Playwright...Testing Libraryのような書き方で記法は違えどテストができる
  • Storybook...いろいろなテストフレームワークで利用ができる(所感)
  • WebdriverIO...Vitestと同じようなイメージ
  • Cypress...spyなど独特な記法があるが、基本的には他ライブラリと同じようにテストが書ける
  • Safetest...アプリのエントリーポイントでSafetestのbootstrapを呼ぶのが他にはない特徴

次にフレームワークごとのベンチマークの話がありました。*1
計測した結果、以下のようになったそうです。

  • Vitest + jsdom...46.31s
  • Vitest(Browser Mode) + Playwright...82.84s
  • Vitest(Browser Mode) + WebdriverIO...195.73s
  • WebdriverIO...65.54s
  • Storybook...80.16s
  • Safetest...29.2s

次に、この結果を踏まえてどのような違いが考えられるかという話がありました。
まず、コンポーネントレンダリングされる場所が違うということで、Node.jsで完結するのかは差異として出てくるということです。
また、ブラウザの自動操作をする際のアーキテクチャも違うため、Webdriverに関しては間にDriverがある分一方向通信が必要で実行時間が長くなってしまうということです。(CDPでは実行時間の問題は解決されるもののブラウザがChromiumベースであったり、Cypressではブラウザ上にテストランナーが独自に存在している)
最近では、Webdriver BiDiという新しいプロトコルの仕様策定が進んでいるそうで、CDP/Webdriverのデメリットをそれぞれ解決することも目指されているということです。

最後に、コンポーネントテストの効果に関する考察がありました。
jsdomを使ったコンポーネントテストはNode.jsで完結し導入コストが低いものの、複雑なコンポーネントテストには向いていないという話がありました。また、シンプルなコンポーネントテストだと思っているテストに対して簡単にテストを書けるのか?というのを見定めるために有用なのではないかということです。
また、ブラウザを使ったコンポーネントテストをすると、信頼性が高く複雑なコンポーネントテストの第一の選択肢になると考えているということでした。一方でexperimentalなものも多かったりするのは今後注視していく必要があるそうです。

また、nus3さん個人としてはApp Routerに刷新されたNext.jsがどうコンポーネントテストと関係していくのか気になっているということでした。

上手に付き合うコンポーネントテスト

続いて@Quramyさんから話がありました。

自動テストは開発規模が増えていってもスピードを損なわずに関係を続けていくために重要だと思っているそうです。
コンポーネントテストは運用コストも安くはないので新規PJのときは使わないこともあるそうですが、Storybookで後から導入できるようにしておくことは常にしているということでした。*2

Storybookを使う際には、お金があるならChromaticをまず使うといいのではないかと思っているということで、やはりオフィシャルサービスは強いそうです。
他にもLost PixelやStorycap、Storybook/test-runner、storycap-testrun、Jest/Vitestなどが候補にあるということでした。

運用の際には実行時間をとにかく落とすことが重要だということで、個人的な見解では5-10分くらいが閾値になってくるということです。
実行時間を速くするには、

  • 札束で叩いてCIの実行環境をCPU増強して並列実行
  • スケールアウト的な発想でGitHub Actionsのmatrixなどで並列ジョブ実行
  • ブラウザを使ったテストを削る

をするということでした。

また、Flaky Testが起きないように注意しているということで、100ピクセル程度(0.01%)は差異が起きても妥当と判定したり、コンポーネントの一部が不安定な場合はVRT時のみ別divに差し替えてFlaky Testにならないようにしているそうです。(どうしてもだめならskip)

急拡大するナレッジワークの開発組織を支える E2E テスト基盤

最後に鳥居さんから話がありました。

ナレッジワークではPlaywrightを採用していて、FrontエンジニアとQAエンジニアが共同でテストを実装しているということです。
E2Eテストの役割としては、基本的な機能のデグレードがないことを保証したりモジュール単位のテストでは不安なシステム全体のテストをするようにしているということでした。

続いて、E2Eテストをしているなかで直近直面した課題と解決策に関して話がありました。
まず、同じテナントで同時に複数人同時にテストを実行すると落ちたりしてしまうということです。
そこで、テナントプールを使用して解決を試みているということでした。
次に、認証周りに関して開発環境限定のテスト用APIを使っている関係で本番環境でテストができていないことが挙げられていました。
この問題に対しては、Testing Gatewayを使っているそうです。
最後に、テナントのセットアップ方法がわからないという話が出ていました。ここは地道にリバースエンジニアリングをして手順をドキュメント化したそうです。

会全体を通した感想

コンポーネントテストに関して、実行速度の問題はやはり課題感として大きいんだろうなあと思いながら話を聞いていました。

Unit Test周りの話が具体的にはそこまでなかった気はしたので、もう少し詳しくこのあたりが聞けると良いなあとは思いました。

*1:ただしデフォルトだと並列実行ができないCypressと用意したテストケースの書き方が複雑すぎて分からなかったPlayWrightは除外。また、Storybookのビルドやアプリのサーバー起動が必要だが時間を含められておらず、Vitest(Browser Mode) + WebdriverIOではVitest側からproviderOptionsを使って並列実行の設定を渡せていない

*2:ただし@QuramyさんはStorybookが嫌いで、experimental RSCがRSCでもなんでもないのにGoを出したということに全く信用を置けない