マイナビ出版から出版されている「単体テストの考え方/使い方」を読みました。
- テストを書くときに何をテストすれば良いか分からなくなるときがある
- テストを読むとき、モックを使われると何をテストしているのか分からなくなる
実務をする中で、上記のような課題感を感じていました。
何かしら書籍を通じてこの課題感を解消できないか考えていたところ、こちらの本に出会いました。
評判も上々で、課題感を解消してくれそうな予感です。
この記事では、テストをどのように書いていけばよいか日々迷っている方向けに、「単体テストの考え方/使い方」の書籍が一種の道を示してくれるのかをお伝えします。
観察可能な振る舞いをテストする
テストにおいて「プライベートのメソッドをテストすべきか」という議論をよく見かけます。
本書においては「観察可能な振る舞いをテストする」というのが指針となっていました。
「観察可能な振る舞い」とは、
- クライアントが目標を達成するために使う公開された操作
- クライアントが目標を達成するために使う公開された状態
のいずれかを指します。
「公開された」とあるので、プライベートなメソッドはテストしない、パブリックなメソッドの呼び出しを通してテストするというのが良いようです。
「状態」も公開されたものしかテストすべきではないので、アサーションにプライベートなプロパティも含めるべきではないということですね。
観察可能な振る舞いのみをテストしようとすると、おのずとAPIは正しい設計に近付いていきます。
「観察可能な振る舞い」の対局は「実装の詳細」です。
「パブリック・プライベートな実装」と「観察可能な振る舞い・実装の詳細」の関係はよく分からなくなるので、まとまった表を以下にメモしておきます。
観察可能な振る舞い | 実装の詳細 | |
---|---|---|
パブリック | パブリックにすべき | パブリックにすべきでない |
プライベート | 該当しない | プライベートにすべき |
良い単体テストを構成する4本の柱
良い単体テストを構成する要素が4本の柱として挙げられていました。
- 退行(regression)に対する保護
- リファクタリングへの耐性
- 迅速なフィードバック
- 保守のしやすさ
4本の柱が挙げられているものの、これらをすべて満たすテストは存在しないそうです。
なぜなら、退行に対する保護と迅速なフィードバックはトレードオフだからです。
残りの2本にも特徴があり、リファクタリングへの耐性は「ある」か「ない」かのどちらかしか成立しない、保守のしやすさは常に最大を目指すとのこと。
どうやってテストを書くか迷ったときには、この4本の柱を基準にどう書くべきかを考えていきたいです。
何を単体テストの対象とするか
単体テストでどこまでカバーするか、統合テストは何を対象とするか、明確な基準を持っていませんでした。
この書籍では、単体テストのみならず、統合テストとはどうあるべきかについても書かれていました。
「コードの複雑さ・ドメインの重要性」と「協力者オブジェクトの数」を軸に判断する方法です。
「コードの複雑さ・ドメインの重要性」は文字通りですが、「協力者オブジェクト」は聞き慣れないワード。
正確に理解できているか怪しい部分ではありますが、自分の中では値オブジェクト以外を協力者オブジェクトと理解しています。
- 「コードの複雑さ・ドメインの重要性」が高く、「協力者オブジェクト」が少ないコードは単体テスト
- 「コードの複雑さ・ドメインの重要性」が低く、「協力者オブジェクト」が多いコードは統合テスト
上記のような住み分けをするようです。
該当しないコードについては、
- 「コードの複雑さ・ドメインの重要性」が高く、「協力者オブジェクト」も多いコードはリファクタリング
- 「コードの複雑さ・ドメインの重要性」が低く、「協力者オブジェクト」が少ないコードはテストしない
ということで、テストしないという選択肢もあることに驚きです。
これも4本の軸の「迅速なフィードバック」を得るためのことなのでしょう。
観察可能な振る舞いは何かを考える
観察可能な振る舞いをテストするというのは、何をテストするかを判断する上で重要な軸となりそうです。
それだけでなく「クラスやメソッドを参照するアクター側からどんな振る舞い期待されているのか」という視点を持ってテストを考えることができるので、設計の改善にも役立ちそうです。
単体テストに対してのみ適用して考えるのではなく、もっと観察可能な振る舞いを具体化して設計にも活かしていきたいですね。
4本の柱を意識してテストを作成する
これまでテストを作成するときは「意図したとおりに動くのか」ということのみに着目していました。
しかし、それだけでは今後の運用に耐えうるテストとなるかどうかは不明なため、しっかりと運用も見据えた4本の柱をどの程度満たすのかという基準を持ってテストを作成したいです。
特に「ある」か「ない」かのいずれかしか取り得ない「リファクタリングへの耐性」と、トレードオフとならない「保守のしやすさ」については、できる限り運用しやすいものを目指していきたいです。
モックすべきものとそうでないものを切り分ける
書籍内ではモックについても多くのページで取り上げていました。
基本的にはモックを使うと壊れやすいテストになるので使わない方向で、という古典学派の書籍ではあるものの、一定モックを使うべきケースというのを紹介しています。
これまで自分はよくインフラ層の処理をインターフェースで定義して、ユースケースではモックして使っていました。
本書では、インフラ層のクライアント部分をモックして、それ以外の処理はモックしないようにすることで、テスト可能な範囲を増やすということも紹介されていました。
「そういうやり方もあるのか…」と感心したものの、どこまで取り入れるかはしっかり考えていきたいですね。
この記事では「単体テストの考え方/使い方」を読んで得た、テストに対する考え方の一部を紹介しました。
テストに対する迷走感は、本書を読むことで一定取り除かれた気がします。
一方で、古典学派と呼ばれる方々のテストに対する考え方は学べたものの、対極として挙げられていたロンドン学派については不明な部分も多かったです。
ロンドン学派についてはバイブルと呼ばれている「実践テスト駆動開発」を読んで少し理解が深まったので、別の書評記事で紹介しています。
ぜひ、そちらの記事もご覧ください。
「単体テストの考え方/使い方」について、まだまだ紹介しきれていない部分も多いです。
おすすめの本ですので、ぜひ手にとって読んでみてください!