【読書感想文】単体テストの考え方/使い方【書評】
2023-03-05Content
はじめに
おはようございます!こんにちは!こんばんは!
のふのふ(@rpf_nob)と申します!!都内のスタートアップでフロントエンドエンジニアとして働いています。
今回は単体テストの考え方/使い方を読んだので感想・レビューを書いていきたいと思います。
ソフトウェアテストについては、「ソフトウェア品質を高める開発者テスト」を以前読みましたが、ソフトウェアテストの概要的な内容であり、単体テストにフォーカスしているこちらの本に興味を持ちました。あと、有名な t_wada さんも絶賛していたというのも読む動機になります。
単体テストの定義
まず序盤の1・2章あたりで単体テストと統合テストの違い(古典派における)が明確に書いてあり、本書の前提条件が分かりやすく感じた。また、古典派閥とロンドン派の違いと本書はどっちの派閥なのかも明確に書いているので内容に一貫性があるのでとても読みやすかったです。
単体テストは以下の通りで、これを満たさないものはすべて統合テストである。
- 1 単位の振る舞いを検証すること
- 実行時間が短いこと
- 他のテストケースから隔離された状態で実行されること
これに加えて7章では、コードの複雑さやドメインにおける重要性の観点と協力者オブジェクトの数の観点からプロダクションのコードを以下の4つに分けることができるという説明から、「過度に複雑なコード」を「ドメイン・モデル/アルゴリズム」と「コントローラ」に分割しリファクタリングしていくところの流れが、とてもわかりやすく説明されており、とても勉強になりました。
また、本書だと、「ドメイン・モデル/アルゴリズム」を単体テストをし、「コントローラ」を統合テストをするというように明確にしているし、モックも結合テストのみに限定するのをベストプラクティスとしているので、個人的に悩ましかったモックの使い所が明確になりました。
このあたりの考え方はフロントエンドの内容に置き換えた場合でも活用できると思いました。
詳細ではなく振る舞い
良い単体テストを構成する 4 本の柱が以下のように挙げられていますが、すべてを兼ね備えることはできないので、まずはリファクタリングへの耐性をメインにすべきと説明されています。
- 退行(regression)に対する保護
- リファクタリングへの耐性
- 迅速なフィードバック
- 保守のしやすさ
「リファクタリングへの耐性」の説明の中で、実装の詳細でなく最終的な結果(振る舞い)をテストすることで、リファクタリングによるテストが壊れることが少なくなり(偽陽性が減る)、より持続可能なプロダクトになると説明されています。
このあたりをフロントエンドのコンポーネントテストに置き換えると、Enzyme が実装の詳細で、Testing-library だと結果を確認する感じなので、Testing-library 使っていれば基本的にリファクタリングに強くなると感じた。React の公式 Doc でも Testing-library を推奨されますし、今後も Testing-library 使うので問題ないと思います。
以下の Kent C. Dodds さんの記事がものすごくわかりやすくこのあたりのことを説明されています。
単体テストアンチパターン
プライベートメソッドを単体テストする
コンポーネントで複数の state や props の値からレンダリングの条件を util 関数で取得したりする場合に、この util 関数はプライベートメソッドのような扱いになるので、単体テストすると実装の詳細をテストしてしまっているような気がした。この場合は state や props の値(入力)からコンポーネントの状態をテストするのが振る舞いをテストしていることになるのではないでしょうか。業務でこういうテストを書いてしまっているなと思った(最近レビューでテスト追加しても良いかもと安易に指摘してしまってので反省・・)
プライベートな状態の公開・プロダクションコードの汚染
Storybook 用に公開してたり、プロダクションコードを汚染している箇所もあるなぁと思った。微妙な違和感があったけどうまく言語化できていなかったが、本書を読んだことで言語化できるようになったのでよかったです。
その他
その他はさくっと書いていく
パラメータ化テスト
Golang で推奨されているテーブル駆動テストのことだと思う。ただ、フロントエンドのテストではあまり出てこないのでちょっと考えたけど、コンポーネントテストだとインタラクティブなアクションなどもあるので書きにくいので微妙な感じはした。普通の入出力がある関数であれば Jest でも each でサポートされているので書いても良いとおもいました。
AAA パターン
フロントエンドのコンポーネントテストだと、コンポーネントのレンダリング部分が Act だと思っていたが、Testing-library の Example だとレンダリングまでを Arrange に含めていた。ただ、コンポーネントテストだと click や type などのインタラクティブな操作を複数行ったりするので、Act は 1 行にならないとそもそも分割がおかしいというのには当てはまらないでも良いし、Act→Asert の流れが複数回ある AAAAA パターンにもなりうるなと思った。
まとめ
単体テストの考え方やその実践方法までわかりやすくまとめられている名著だと思いました。あまり多くの技術書を読んでいるわけではないですが、個人ベスト 3 には入りました。テストの実装や考え方についてもやっとしたら、すぐに本書に立ち返ることになると思います。
内容やサンプルコード自体はバックエンドのテストが中心でしたが、フロントエンドエンジニアの方にもとてもおすすめできる書籍だと思います。単体テストがなぜ必要なのかと か良い単体テストはどういうものなのかとかは基本的にフロントエンドでも同じです。
フロントエンドのテストの書籍が 4 月に発売されるみたいなので、そちらも読んでみて、本書を読んで考えたことがどれくらいあっていて、どれくらい違うのかなど、また新たな気づきが得られればいいなと思います。
今回は単体テストの考え方/使い方の感想文を書きました。
こちらの記事を読んで、ちょっと違うなとか、ここってこういうことじゃないのとかあったら DM などで教えていただきたいです 🙏
最後まで読んでいただきありがとうございます!! この記事が良かったと思ったら SHARE していただけると泣いて喜びます 🤣