TDD

今からでも遅くない、xUnitでテスト駆動開発を実践するためのテストパターン -- Part 1: テスト戦略

テスト駆動開発っていいよね

プロダクトコードをいじる前に、まずはテストコードを書いてから、プロダクトコードを書きます。
最初のプロダクトコードではテストは落ちるけど、一通りいじり終わってから、テストをもう一回流して、テストが通ったら出来上がり~

テストコードを先に作っているから、テストしづらいプロダクトコードにはならないはずです!
そして、保障したい動作も振る舞いも全部テストコードに書いておけば、境界値周りのプロダクトコードの動きも心配要りません!

テスト駆動開発は素晴らしいですよね!ぜひぜひ開発の現場で実践したいですよね!

あ、プロダクトコードとテストコードが長いので、これからソースとテストを略させてください。テスト駆動開発もTDDと略させてください。

でもうちじゃ無理だ、と思ったりする?

うちの現場はカッチカチな密結合のレガシコードばかりで、TDDはAPI設計の段階から気をつけてやらないと無理だろう、と思って、実際始める前に諦めていませんか?

実は、いくつのユニットテストパターンを適用することで、密結合なレガシコードでもTDDでやっていけるかもしれません。

以下では、二部構成でその裏にある基本的なテスト戦略と、実際のパターン紹介と適用場面を順に説明していきます。

この記事は主にテスト戦略に着目します。
パターンの方は実際のコード適用例を交えて説明していきたいと思います。

本題に入る前にちょっとした用語集

  • SUT1: テスト対象となるコンポーネント
  • DOC2: テスト対象となるものが依存する別のコンポーネント

  • 間接入力: SUTが呼び出すDOCのメソッドのうち、その戻り値や例外が、SUTの振る舞いを影響するもの

  • 制御ポイント: SUTの振る舞いを制御するため使った間接入力

  • 間接出力: SUTが呼び出すDOCのメソッドのうち、その引数または呼び出しそのものが、SUTの振る舞いに影響されるもの

  • 観測ポイント: SUTの振る舞いを観測するため使った間接出力

基本的な戦略 -- 外堀をうまく使う

密結合しているコードのうち、テストしたい部分(SUT)と、依存されている部分(DOC)をまず見分けます。
本命(SUT)とその周りの親友たち(DOC)をちゃんと区別して、外堀を埋めてから本命を落とす、というのが基本的なコンセプトになります。

うーん、なんか恋愛ゲームっぽい説明ですね。でもしっくり来るから恋愛ゲームを例に説明し続けます。

SUTの制御 -- 周りをうまく使ってフラグを立てる

SUTの制御は普通、SUTの外部向けメソッドを使って、引数の値で制御します。
外部向けのメソッドだけで制御しきれない場合、もしくは制御するためのメソッドがない場合、DOCの制御ポイントを使います。

恋愛ゲームを例に説明すると、こんな感じになります。

  • 攻略キャラとの会話 = SUTの制御用メソッド
  • 攻略キャラと直接関係していないイベント・周りのキャラとのイントラクション = DOCの制御ポイント
  • エンディング = SUTの実行フローによる観測可能な最終出力

攻略キャラとの会話をこなしつつ、周りのイベントをそれっぽい方向に持っていけば、狙いのエンディングに行けるはずです。

SUTの観測 -- 好感度チェックはヘルプキャラに聞く

SUTの観測も普通、SUTの外部向けメソッドを使って、戻り値が期待した通りかどうかで観測します。
外部向けのメソッドでの観測が不十分な場合、もしくは観測するためのメソッドがない場合、DOCの観測ポイントを使います。

恋愛ゲームを例に説明すると、こんな感じになります。

  • 攻略キャラとの会話・会話時の立ち絵 = SUTの観測用メソッド
  • 好感度を教えてくれるヘルプキャラ = DOCの観測メソッド
  • 好感度の増減 = SUTの振る舞いが期待通りになるかの判断基準

攻略キャラとの会話や立ち絵だけでは分からない好感度増減は、ヘルプキャラに聞けば多少は分かるでしょう。

DOCの制御と観測 -- 自作自演でそれぽく見せる

上では、外堀を埋めるという表現使ってましたけど、厳密にいうと、SUTに、外堀は埋まったように見せるです。
何故かと言うと、DOCに必要な制御用メソッドと観測メソッドが揃っているとは限らないからです。

実際、SUTとDOCとのイントラクションはメソッドベースがほとんどなので、DOCと同じAPIを持つ何かを、SUTから見たDOCのポジションに置けば、DOCによる制御と観測と同じ効果を達成できます。

このDOCと同じAPIを持つ何かを、Test Doubleと呼びます。これはあとで説明するテストパターンの中心となります。

恋愛ゲームを例に説明すると、こんな感じになります。

  • 攻略キャラを絡む本物の不良 = DOC
  • 不良っぽく攻略キャラを絡むと、主人公に頼まれた善良な市民 = Test Double
  • 不良を撃退した主人公が格好良く見える(攻略キャラ視点) = 制御ポイントによるSUTの制御

例えば自作自演でも、格好よく不良を撃退したところを見せたら、攻略キャラの好感度も上がるのでしょう。
若干クズな主人公ですが、ここは気にしないでおこう…

つづきは明日

テスト戦略を簡単に説明するつもりでしたが、意外と長くなりました。

というわけで、パターンは次回(明日)の記事で説明していきたいと思います。


  1. "System Under Test"の略です。 

  2. "Depend-On Component"の略です。