アジャイル宣言の共著者であるBob Martin氏は、共変性のある構造を持つコードとテストを記述してしまうという落とし穴の概要を説明したブログを公開した。本質的には、テストの構造は反変性を持つ方法で設計されるべきであり、壊れにくく、コードベースをリファクタリングしやすいように製品コードとは疎結合にすべきであると彼は強調した。
TDDに取り組む際の問題の1つは、しばしば脆弱なテストプログラムを記述してしまうことである。Martin氏は、これはテストコードがあまりに製品と密結合になり、テストも同時に書き直さないとほとんど何もリファクタリングできない事態であると説明した。彼は以下のことを強調した。
テストの構造は製品コードの構造を反映してはなりません。なぜなら、密接に結合していることでシステムが脆弱となり、リファクタリングを妨げるからです。むしろ、製品コードとの結合を最小限にするために、テストの構造は独立に設計されるべきです。
この脆弱なテストプログラムの問題を詳細に説明するために、これはリファクタリングが何か理解しない結果引き起こされるものであるとMartin氏は指摘した。”リファクタリングは、テストがずっと成功する状態のままで行う一連の小さな変更であると定義される”。テストが製品コードと結合しており、テストが製品コードの振る舞いに着目せずに行われているのであれば、リファクタリングの余地は無くなっていく。
この共変構造はTDDの誤解からも生じるものであるとMartin氏は記述した。1つのクラスに対してテストクラスは1つであるべきだと考えがちだが、実際にはテストは自身特有の構造を持つべきである。結局、テストされるべきなのはアプリケーションの振る舞いであって、コードの構造ではないのである。
Martin氏は、クラスとテストが直接対応している状況から、開発が進むにつれてそれら2つがどう自然に別れていくかを説明している。最初の例では、パブリックメソッドのコードからプライベートメソッドを抽出する場面を説明している。ここでは、アプリケーションの振る舞いにおいては同じテストカバレッジを保ちながら、直接テストはされない新しいメソッドを導入している。コードがクラスに抽出されたときも適用される原則は同じである。全てがもともと存在するテストクラスでテストできている間は新しいテストクラスは必要ない。
時が経ち開発が継続される間に、より多くのテストが追加されてこれらのテストそれぞれがアプリケーションの特定の振る舞いを確認していく。完全な仕様が完成したときには、それら全ての振る舞いを満たすために、自然にアプリケーションコードはより抽象化されている。言い換えると、製品コードは常により抽象化される方向に進みつつ、テストコードはより具体化されるべきである。このことが疎結合を導き、故に反変性を示すのである。
テストがより具体化されるにつれて、製品コードはより抽象化されていきます。新しく失敗するテストが書かれるまでは、この2つのコードの流れは普遍性の軸に沿って対称の方向に移動するのです。
ブログの全文はこのURLからオンラインで読むことができる。
Rate this Article
- Editor Review
- Chief Editor Action