対象読者
- TDDに興味をお持ちの.NET Frameworkの開発者
必要な環境
サンプルコードを試してみるには、Visual Studio 2013のUpdate 2以降が必要です(無償のExpressで可)。本稿執筆時点では、下記から入手できます。この記事では、Visual Studio Express 2013 with Update 3 for Windowsを使用しています。
OSにはWindows 8.1が必要です(2014年4月のアップデート、通称「Update 1」が必須)。さらに、Windows Phoneのユニットテストを実行するためには、64bit版Windows 8.1のPro版以上とSLAT対応のPCが必要になります。
なお、Expressエディションは複数存在していてまぎらわしいのですが、「for Windows」を使います。「for Windows Desktop」は、WPFとWindows Formsの開発用です。
はじめに
TDDはパーツを制作する手法
最初に少しばかり寄り道を。
最近、TDDとATDD(受け入れテスト駆動開発)を区別しない意見に出会いました。スペック注1を決めるのはステークホルダーなのだから、TDDはオンサイト顧客を持たない限り成り立たない、というような話でした。ほんとうにそうなのでしょうか?
TDDとATDDでは、決定すべきスペックの質が違います。レイヤーが違うといってもよいでしょう。
-
ATDD:
受け入れテストとして、アプリのスペックを決める -
TDD:
ユニットテストとして、パーツ注2のスペックを決める
例えば、とある画面のスペックを決めているところだとしましょう。立場の異なる2人が、次のように言いました。
-
ステークホルダー:
「☆☆画面で○○ボタンをクリックしたら△△処理をした結果が表示される」 -
開発者:
「☆☆画面クラスは○○ボタンクリックイベントで△△_Commandを発行する」
前者は、アプリのスペックを言っています。そこには、△△処理のすべてのテストケースも(暗黙的に)含まれています。受け入れテストは、このレベルのスペックを確認します。
後者は、パーツ(ここでは画面のクラス)のスペックを言っています。パーツとして見た場合は、ボタンクリックでコマンドが正しく発行されることさえ確認できればOKです。TDDのユニットテストは、このレベルのスペックを確認します。
この両者、明らかに質が違いますね。そして、アプリのスペックを決定する責任を持つのは、ステークホルダーだということには、異論はないと思います。では、パーツのスペックを決定する責任は誰にあるでしょう? コマンドを発行するのか、メソッドを呼び出すのか、どちらにするかを決めるのは開発者の責任です。
- アプリのスペックをパーツのスペックにブレークダウンしてから、テストファーストする
- パーツのスペックを決めるのは、開発者の責任
なお、一般的にUIそのものをテストファーストするのはコストが見合わないので、TDDで作ってはいけません(勉強や実験のためなら構いませんが)。今回取り上げるのは、UIそのものではなく、テストファーストしやすいビューモデルです。
状態を持つクラス
パーツのスペックを決めるとき、やっかいなのは内部に状態注3を持っているクラスです。その状態によって挙動が変わるメソッドやプロパティ、あるいは、状態の変化によって発火するイベントなど、どれも単純なメソッドのようにはスペックを決められないでしょう。スペックを決められないと、テストファーストを始められません。
状態を持つクラスは、第5回『TDDBC大阪の課題をC#でやってみる ~ クラス設計とTDD』(課題は自動販売機)でも扱いましたが、そこではTDDBC大阪の課題を解くことに重点をおいていました。そこで今回は、あらためて状態を持つクラスをテストファーストで作る方法に焦点を当てて考えてみましょう。
外部設計(external design)のこと。概要設計と混同しないよう、本稿ではこの言葉を使います。
部品。クラス、メソッド、プロパティ、イベント、デリゲート、演算子など。本稿では、特にユニットテストの対象にできるものを指します。
ここでは、クラスのインスタンスが保持しているデータ。一般的にはメンバー変数のこと。デザインパターンの一つである「State パターン」にいう状態とは異なります。
「TDDって何だっけ?」と感じたときは、スタート地点を振り返ってみましょう。
次は、TDDの提唱者であるKent Beckの著書『Test-Driven Development: By Example』(訳書『テスト駆動開発入門』)からの引用です(日本語訳は筆者)。
テスト駆動開発において我々は、
- 自動テストが失敗している場合に限り、 新しいコードを書く
- 重複を取り除く
これらは 2つのシンプルな規則だ。
この2つの規則は、プログラミングのタスクに対する指令を意味する。
- レッド -- 動かない (たぶん最初はコンパイルすらできない) テストを少し書く。
- グリーン -- テストを速やかに動くようにする。その過程で必要ならどんな罪をも犯す。
- リファクタリング -- テストを動くようにするために作られたにすぎない重複をすべて除去する。
レッド / グリーン / リファクタリング -- TDD の呪文
この文章をいつでも見られるように、A3ポスター「TDD MANTRA」にしてみました。筆者のOneDriveフォルダーからダウンロードできますので、どうぞご利用ください。