家永さんのコメント
そうですね。
今「モックテスト」
モックオブジェクト技法とは
「モックオブジェクト」
詳しくは後述しますが、
メリット1:協調オブジェクトの開発前でもテストができる
たとえば図のように、
A、
しかし、
そのようなときに、
たとえば、
今テストしたいのはBやCではないので、
メリット2:対象を絞り込むことで、加速力が得られる
モックの動きというのは、
資産価値が高いテストのスコープは、
スコープを絞ることには利点があります。スコープを絞るのですから、
またグリーンになったテストとそのクラスは、
モックオブジェクト技法は、
メリット3:作成が難しいオブジェクトや、作成が難しい状況をシミュレートできる
繰り返しになりますが、モックオブジェクト技法とは、テスト用に作成する偽物でした。偽物にテスト用の振る舞いをさせることができるということは、「もしもこうなったら」という状況をシュミュレートできるということです。つまり、実際のシステムで再現するのは難しい例外系のテストを簡単に行うことができます。
たとえばネットワークエラーが起きた場合の振る舞いのテストは、ネットワーク通信を行うクラスのモックを作り、そのモックからネットワークエラーをわざと発生させることによって簡単に行うことができます。
デメリット:仕様変更
しかし、モックオブジェクト技法もいいところだけではありません。
モックオブジェクト技法を使ったテストと普通のテストの違いは、仕様変更のときに現れてきます。
たとえば本物のクラス同士でテストを行う結合テストのような、ユニットテストよりも広い粒度のテストの場合、本物のオブジェクト同士が話し合うので、仕様変更を行われた場合には、当然その仕様変更に則ったテスト結果になります。
でも、モックオブジェクト技法を使う場合には話が変わってきます。モックオブジェクト技法を使う場合には、プログラマが自分の考えで仕様をシュミレートします。すると、モックオブジェクトが真似する対象の仕様に変更が発生したとき、モックも仕様に合わせて変更しないと、テストで考えている仕様と現在の本当の仕様が食い違ってしまう可能性が出てきます。
例を挙げて具体的に
例を挙げて、もう少し具体的に説明しましょう。
あるプロジェクトで、モックオブジェクト技法を使って、一つ一つのテストの視点を絞って実装を各個撃破していきました。各クラスを個別に開発したあとに、実際の本物のオブジェクト同士を話し合わせるテストもようやくグリーンになり、まず最初の段階はうまくいきました。
あるとき、お客さまの「今度はこういう機能作ってほしい」というお話を受け、クラスA、B、CのうちCに仕様変更や機能追加が入り、Cが全然違う形に変更され、Cの動きも変わってしまいました。
Cの動きが変わったので、本物を話し合わせるテストは、何もしなくても動きが変わります。しかしモックテストで作成したCの偽者自体は、モックのコードを手で直さない限り動きは変わりません。
本物のCの変更に合わせて、Aもコードを変更しなければならないというときに、本物を使う大きい視点のテストならば、Cの仕様変更に応じてAのコードを変更すれば、Aも動くようになります。
しかしAのみを対象にした小さいモックテストはどうでしょうか。AのテストにはCの偽物が使われています。もしもAを仕様に合わせて変更したとしても、Cの偽物を仕様変更に合わせて変更してはいないので、Cの偽者が前提だった小さいテストは全滅してしまうのです。
Aのモックテストが動くための前提が変わってしまったということです。「Cの偽者のメンテナンスをいくつやらなければならないんだろう」というような状況になってしまいます。
もう一度、テストの資産価値
そういうときには、前回のテストの資産価値の話を思い出しましょう。「大きい視点のテストはもうできあがっていて、かつそのテストがグリーンになっているので、モックオブジェクトベースの小さいテスト群はもう役割を終えたのではないだろうか」と、考えます。
Aをまず最初に開発するために、加速力をつけるためにモックオブジェクトベースで小さい視点のテストを行った。それらモックオブジェクトベースのテスト群は、もう役目を果たしたので、大きい視点のテストでレッドとグリーンのサイクルがまわせるようになったときには、小さい視点のテストはもういらないかもしれない。という考えが、テストの資産価値という考え方でしたね。
実際モックオブジェクトや小さいユニットテストの範囲で開発をまわしていくときには、仕様変更があってメンテナンス対象のインタフェースが変わったり、メソッド名が変わったときに、多量のコンパイルエラーが出てしまったりとか、たとえコンパイルエラーが出なかったとしても、レッドバーがたくさん出てしまう場面によく出会います。
大きいテストが成功しているとき、つまり本来必要な修正作業自体は成功しており、モックを本物に近づけるためのメンテナンスだけが残っているような場合には、テストとして価値の低いものは、強い理由がない場合には、消してしまうという選択も、メンテナンスコストを下げるために、プロジェクトをこれからまわしていくために、必要になってくるのではないかというのが私の意見です。
繰り返しになりますが、
たとえばネットワークエラーが起きた場合の振る舞いのテストは、
デメリット:仕様変更
しかし、
モックオブジェクト技法を使ったテストと普通のテストの違いは、
たとえば本物のクラス同士でテストを行う結合テストのような、
でも、
例を挙げて具体的に
例を挙げて、
あるプロジェクトで、
あるとき、
Cの動きが変わったので、
本物のCの変更に合わせて、
しかしAのみを対象にした小さいモックテストはどうでしょうか。AのテストにはCの偽物が使われています。もしもAを仕様に合わせて変更したとしても、
Aのモックテストが動くための前提が変わってしまったということです。
もう一度、テストの資産価値
そういうときには、
Aをまず最初に開発するために、
実際モックオブジェクトや小さいユニットテストの範囲で開発をまわしていくときには、
大きいテストが成功しているとき、