2010年6月7日月曜日

mocking の要点

モックを使うと何がどう変わるかを、単なる assertion と比較して考えてみる。

例として、以下のような testTarget のテストを考える。testTarget オブジェクトは foo() 呼び出しの中で、collaborator の bar() を呼び出す。この testTarget → collaborator の関連は、クラス図や CRCカードにも明記されるような、れっきとしたクラスの仕様であるとする。

これを xUnit の昔ながらの assertion でテストすると、下図に示すように、テスト・コード管理下に入るのは foo() 呼び出しの条件と結果となり、カバレッジに含まれるのは赤の網掛けの部分となる。

ここでまずい点が三つある。

① testTarget と collaborator の協調がテストされていない。collaborator を正しい条件で呼び出しているか、また得られた結果を正しく扱っているかが検証されない。(それどころか、collaborator を呼ばないダミーコードが実装し忘れたまま残されていたとしても、テストコード側では認識しようもない。)

② テスト対象外のコードまでがカバレッジに含まれてしまっている。collaborator のコードは、collaborator のテストコードが書かれて始めてカバレッジに含まれるようにしないと、網羅率が正味のテスト実施状況と乖離してくる。テスト漏れも生じやすくなる。

③ collaborator の bar() を実行するために、リソースやらコンテナやらのセットアップが必要な場合、テストコードが煩雑になる。また多くの場合、テストの実行速度も物凄く遅くなる。

これに対し、xMock を導入して assertion と併用すると、上述の問題が改善できる。

上図は collaborator をモック化した場合のもの。collaborator 呼び出しの条件がちゃんと検証され、返される結果もテストコードからコントロールできるようになる。カバレッジはテスト対象コードのみとなり、リソースをセットアップする手間もなくなって実行時間も早くなる。

デメリットがあるとすれば、テクニック的に assertion よりは若干難しい事くらいだろうか。他のクラスとの協調も検証対象になる分、書かなきゃならないテストコードの量が多くはなるが、本来テストすべきだった事ができるようになっただけなので、別にデメリットという事にはならない。

0 件のコメント:

コメントを投稿