この本を読もうと思った背景
先に「レガシーコードからの脱却」を読んでいたため
- テストは外部から見た振る舞いを記述するもの
- テストがあることでデグレを恐れずリファクタリングを行うことができる
等の保守性におけるテストの重要性は知っていたのですが、実際に業務でテストを書いてみると、
「テストが1つ1つ長いし、後から見て読みづらい」
「もっと綺麗に書くにはどうすれば良いのだろう?」
と毎回悩むはめになりました。
そこで今回、テストに焦点を当てた本を読むことで、テストコード自体の保守性を高めたいと思いました。
感想
テスト名の付け方などのすぐに改善できる部分も参考になりましたが、最も勉強になったのはプロダクションコードの構造を整理することでテストコードが綺麗に描きやすくなる、という考え方です。
↓ 具体的には以下のような感じ
コードをロジックを扱うクラスと、コントローラーとしての役割を持つクラスに分け、
ロジックを扱うクラスからは
- プロセス外依存(データベースとのやり取りや、メールシステムなど外部サービスとの連携等)
- 協力者オブジェクト(処理上必要な他のクラスとのやり取り)
をできるだけ少なくします。
これらを排除すると、テストがしやすくなります。
例えば最後にデータベースの状態を確認するテストよりも、テスト対象のコードが返す結果を確認する方がシンプルなテストになりますよね。
これらを排除する一方で、複雑な処理はロジックを扱うクラスで担当します(狭く深くのイメージ)。こうすることで、コードの重要性は高いが、テストはシンプルに書ける、というクラスになります。
これが最もテストを重点的に行うべきクラスで、このクラスに対して実行時間の短いテスト(単体テスト)を十分な数書くことが効率的なやり方になります。
逆にプロセス外依存や協力者オブジェクトとの連携、ロジッククラスの呼び出しはコントローラクラスに任せます(広く浅くのイメージ)。
これらに対してテストを行う場合、実行時間の長いテストになりますが、テスト対象クラスでは複雑な処理を行っていないため、何パターンものテストを書く必要はありません。これらはあくまでも各ロジック部分が正しく連携し、全体として機能するかだけを確かめれば良いです(統合テスト)。
このように、単なる小技集ではなく、根本からテストについて考えられているため勉強になりました。
どんな人におすすめできるか
- テストを書くことが保守に役立つ、ということをある程度理解している
- 単体テストと統合テストを意識的に使い分けていない
- 毎回長く読みにくいテストメソッドになってしまう
その他学んだこと(自分用メモ)
テストクラスのコンストラクタで共通処理を行うことは避ける
- 各テストクラスの結合度が高まり、コンストラクタを改修しにくくなる
- コンストラクタを見ないと準備の内容がわからないため、テストが読みにくくなる
- 代わりにファクトリクラスや、ヘルパーメソッドを使う
テスト名は単語間をアンダーバーで繋ぐ
- テストメソッドは他から呼び出されることは無いので、名前の分かりやすさ、読みやすさに全振りして良い
- 単語間をアンダーバーで繋ぐと平文みたいになり読みやすさ向上
観察可能な振る舞いに対してのみテストを行う
- 実装の詳細と強く結びついたテストを作成すると、改修やリファクタリングのタイミングで毎回テストを書き直すことになる
- 外部から観察可能な振る舞いについてのテストは、リファクタリングの影響を受けないため保守しやすい
- 上記を実現するためにはクラスの適切なカプセル化が必要
プロセス外依存のうち、管理下にない依存に対してのみモックを使用する
- 管理下にあるプロセス外依存は実装の詳細として扱う
コメント