はじめにlink
2023/04/24に発売された「フロントエンド開発のためのテスト入門」を読了したので、読みながらとったメモをもとに感想や自分の考えと違ったところなどをまとめる。
全体的に非常に参考になる内容が多いが、特に後半にいくにつれて加速度的に参考になる内容が増え非常に良著であると感じた。
実践Node.js入門でもテストはある程度量をとって記述しているが、テストそのものがメインではないため情報や考え方として落ちている内容の多くがこの本で補完されている。自著を読んだ人には同時に本書もおすすめしていこうと思っている。
自分はフロントエンドのテストはバックエンドに比べて優先度が低くなる傾向にある。
これは自分が扱うサービスがtoB系が多く、表示崩れなどがサービス継続上致命的になりにくいため、気づいたベースで最速で直せる環境があればよいと考えているため。 また、開発者の数が少なく表示は頻繁に書き換わるため表示系にテストのメリットが少なくなりがちという傾向がある。 ロジックに関わる箇所はフロントエンドでもテストを書いたほうがよいが、ロジックの多くはフロントエンドには持つべきではないと考えているためバックエンドのテストの比重が多くなる。
本書はそういった立ち位置の自分に対しても、書くべきテストの範囲やテクニックに気づきを与えてくれた。
内容についてlink
前半はフロントエンドにとどまらずどの言語でも参考になるテストの知識が豊富だった。
後半はフロントエンド開発のためのというタイトルの通り、アクセサビリティやE2Eなどを含むテストをどのように設計すべきか、なぜそうすべきかといった記述が多く、フロントエンドに明るくない人も一通りの知識をつけることができる構成になっている。
1章link
なぜテストが必要なのかという話がメイン。ここで書いてある理由については考えの違いもなくもろ手をあげて賛成という内容だった。
そのうえでチームやサービスの状況によって何をどれだけ採用するかというのがテストのテクニックになると考えている。 とはいえその判断をどうしたらいいのかという判断材料を手に入れていくという考えでこの後の章を読んでいった。
2章link
テストの種類についての話。特にフロントエンド以外ではなじみの薄いであろうe2eやビジュアルリグレッションテストの話があるため、フロントエンドまわりにあまり触れてない人がテストのイメージをつかむのにおすすめな内容。
所謂テストピラミッドやテスティングトロフィーといった概念の説明もあり、どのテストをどれだけ書くべきかといったい汎用的な疑問にもヒントが手に入る。
最後のコラムでは過剰に書きすぎたテストを減らす話も記述されていて、テストのための書籍として現実と理想のバランスをどうとるかという誠実さを感じた。
3章link
単体テストについての話。内容としてはjestを使ったテスト記述の基礎で、そんなに複雑ではないので他のフレームワークや言語を触ったことがある人ならそんなに苦労せず理解できるだろう。
特によかったのは expect.assertion()
でテストのミスを防ぐ記述がされている所。これは他の言語でもでもよくあるミスを含むテストだが、あまり解説をされている記事などをみかけない。expect.toThrow
で担保できるじゃんという話もあるが、このテストは常に期待する結果を返せているのか?という視点をもつにはこういった概念を理解しておくといいテストが書けると考えている。
4章link
モックについての話。モックを全く利用しないというのはほぼ不可能になってきている現状、モックの説明にきちんと章がさかれているのはよいと思う。 また、最初の方にモック、スタブ、スパイの用語の違いが説明されているのも良い点。(近年のライブラリではこのへんがぐちゃっとなってる事が多い)
近年のレイヤードな設計を採用しているプロジェクトではモックを大量に使うようなテストをよく見かけるが、自分自身は意味のあるテストになっている疑問に感じるものが多い。 本書のサンプルはあまりそういった設計やモックの使い方はされておらず、現実に即したサンプルに感じて個人的にはなじみやすかった。
httpリクエストをモックしてその後のロジックをテストするというのは、よく書くテストケースなのでこの章は実際のテストで役立つ知識が多そう。 httpリクエストのモックを返しやすくするutil関数を作る説明している。個人的にはテスト用のutil関数はできるだけ作らずコピペで対応する派。
これは下記記事にも記載されている「あえて頭を悪くして愚直に書く。頭がいいアサーションも、頭がいい context も避ける。」にかなり近い考えを自分が持っているため。
https://zenn.dev/mizchi/articles/my-test-policy
確かにutil関数があるとテストの見た目もわかりやすくドキュメントとしての価値がでる。 が、汎用的に作ろうとするほどutil関数自体にテストが必要になるくらいのボリュームになってしまう事がある。 なのでテストは似ている箇所であってもコピペを許容してできるだけ頭悪く書く(自分はダサく書くと呼んでいる)方がいいと考えている。この章で紹介されているくらいのutil関数であればあまり問題ないとは思うが、if文が内部に登場するのは少し盛りすぎなutil関数のサインと考えている。
自分はできる限りテストケース1つの独立性が高いことの優先順位が高いためコピペを許容することの優先順位が高いが、テストは「ドキュメントとしての読みやすさの価値」も持つので、どちらに完全に傾けるというよりはバランスの問題でもある。
そういった意味ではデフォルト値を定義するfactory関数はいいバランスなのかなと感じた。
5章link
UIコンポーネントテストについての話。主にtesting-libraryを使ってどうやるかという説明が中心。
自分は先述の通りデザイン崩れに対する優先度が低くUIのテストは薄くしがちなのだが、eventに応じてロジックが呼び出されるかというテストはデザインに対する依存が少ないしバグを抑えるメリットが上回るため価値があると考えている。
その観点でfireEventを使うことが多かったが、本書ではユーザーが不可能な操作もできてしまうため特別な理由がないならuser-eventを使う方がよい、と説明されていて確かにと感じたので今後はそうしていこうと思う。
コラムで下記の利用するクエリの優先順位について書かれていた。
https://testing-library.com/docs/queries/about/#priority
自分は普段のテストにおいて、flakyさを排除するために暗黙的な挙動をなるべく含まない事が大事だと考えている。
そのためUIテストを書くときも明確に取得できるクエリを選びがちだったが、「ユーザー操作を限りなく再現する」ことにアクセサビリティも含むのならば、確かにgetByRoleなどの優先順位をあげて利用すべきという内容は確かにそうだよなという納得感を改めて感じた。自分はおそらくテストはロジック中心にin/outが正しく動く事の優先順位が高いためそういう視点になってたんだろうという気づきがあった。
そのため、暗黙のロールで要素を取得する方法はできるだけ避ける事が多かった(これは頭がいいアサーションを避けるにも通じているいかも)のだが、テスト対象にアクセサビリティを自然に含めるなら暗黙のロールを使う方がよいというのは納得感がある方針かもしれない。
また、暗黙のロールでテストを書くことを強制する事で、それで取得しにくいコンポーネントはスクリーンリーダーなどでも取得しにくい=アクセサビリティが悪いというのも説明がしやすく、ただマークアップすればいいから抜け出せるいい視点かもしれないと感じた。
アクセサビリティをテストに含めるなら章後半にある暗黙のロール対応表やアクセシブルネームの確認がとても参考になる。主張もw3.orgなど公式の情報を参照しているため納得感が高い。
4章の感想ではテスト用util関数はなるべく避けたいと書いたが、user.type
などユーザーの入力を複数パターン書く場合、そこはまとめて省力化したいというのは自然だと感じた。この差はどこにあるのかと考えたが、おそらくまとめたところで「そのコンポーネント専用のutil関数」にしかならないからutil関数にテストが必要になるほど複雑化しにくいからじゃないかと思う。それであれば先に優先度高いと述べた「テストケース1つの独立性が高い」とそんなに矛盾しない。なので。util関数を避けるべきは「頭よすぎる=汎用的に作りすぎる」ことなのかもしれない。
やりすぎるとテストランナーの上にコンポーネントに依存したテストランナーを作るのに近いことになりそうなので、どこまで共通化するのかはまだバランスを考えていく必要がありそう。どこからがやりすぎかはまだ言語化はできていない。
章後半で、「準備 -> 実行 -> 検証」の3ステップにまとめられたArrange-Act-Assert(AAA)パターンのテストは可読性が高いと紹介されていた。なんとなくやっていた事だったがパターン名を知らなかったので今後人に伝えやすくなったし、その3ステップに沿っている箇所までなら共通化してよい、とするのはutil関数化の指針としてありかもしれないので検証したい。なんとなくだが「準備」は共通化したい欲が強くわきそうだが、「実行」と「検証」は愚直に書くのが向いている気がしている。
非同期処理はエラー分岐が複雑になるからテストを書いて考慮漏れを書くとよい、というのは全面的に同意。フォームとかはUIテストを書いてペイしやすい部分だろうと思う。
6章link
テストカバレッジについての話。このあたりはテストを書いたことある人はすっと理解できそう。
この章で一番よいと思ったのは「カバレッジの数値は高いからといって品質が高いテストであるとは限らない」と記載されていた事。自分も昔からカバレッジの%だけみてCIを落とすというのは本質的ではないと考えている。テストはあくまで運用や改善の補助に使うためのもので、ただカバレッジを満たす(定量的なもの)ことにとらわれるのはよくないと思う。この記述がテスト本に書かれているのは価値がある。
おわりにlink
フロントエンドのテストって何ぞやって疑問に大体の答えが返せる良著でした。
フロントエンド開発のためのセキュリティ入門と合わせて周囲にもおすすめしていこうと思います。
フロントエンド開発のためのテスト入門読み終わった。かなり網羅的でとりあえずこれ読んだらテスト周りの悩み大体答え書いてあるよって渡せる。実践Node.js入門ではここまでテストに詳しく踏み込めなかったから周りにはこれおすすめしておこうhttps://t.co/NOa3Hs5sKd
— Kohta Ito (@koh110) October 17, 2023