Humble Objectパターンでテスタブルに
Humble Objectパターンとは
Humble Objectパターンはソフトウェアのデザインパターンの1つ。 Humble Objectパターンを用いることで、ユニットテストが書きやすくなる。
Humbleは 「控えめ」 という意味で、テストしにくいロジックとテストしやすいロジックを分離し、 テストにくいロジックが控えめになるよう分割すべき というものになる。
Humble Objectパターンの対象となるもの
Humble Objectパターンの適用が必要なものを考えてみる。
GUI 。一般的にGUIに関する処理はテストがしにくい。iOSアプリ開発で言えば、UIKitに依存した処理はテストがしにくい。この場合は、UIKitに依存する処理をView に該当するクラスに寄せ、UIKitに依存しない処理を Presenter や ViewModel に寄せる。例えば特定条件の場合に文字を赤くするような処理の場合には、UILabelのUIColorの値を出力として検証するのではなく、ViewModelに定義したlet isRed: Bool
のような値を出力としてViewModelをテスト対象にする。
生成処理が隠蔽されているもの 。フレームワークで定義されたクラスでイニシャライザ(コンストラクタ)が隠蔽されている場合などは、そのオブジェクトを生成することができないため、ユニットテストがしにくい。例えばiOSのUICollectionViewCellはインスタンスの再利用を前提とされている。
データストア 。データベースアクセス、通信処理を伴うものはAPI側の状態や通信時間にユニットテストが影響されるため、ユニットテストがしにくい。HTTP通信をスタブするライブラリを利用するという手もあるが、データストアに関する処理は適切に抽象化し、テスト時はモック化することが好ましい。
Humble Objectパターンの要点
プロダクトのテストカバレッジを100%にするというのは、技術的にも費用対効果的にも現実的ではない。そのため、 テストすべき領域とテストしなくても良い領域 をまずプロダクト全体で定義する。
その上で、テストすべきとした領域のテストカバレッジを上げていくのが効率が良い。
また、テスト対象領域をプロダクトで定義した場合、逆にテスト対象でない領域にロジックを書いてしまう力学が働く。この場合は テスト対象でない領域がHumble ObjectになるようコードレビューやLinterなどで指摘 していく必要がある。
Humble Objectパターンの副次効果
Humble Objectパターンを利用することで、特定のフレームワークに依存した処理以外のコアとなるロジックが自然と集約される。例えば、iOSのUIKitやmacOSアプリのAppKitに依存する処理と、アプリケーション本来のフレームワークに依存しない処理が分離されるため、それぞれに対してユニットテストを書く必要がなくなりモジュールの再利用性が高まる。