NUnitでBDD-素振り重要 (>_<)

TDDを始めたばかりでつまづくのは、テストという言葉にとらわれているからだ。テストと聞くと、あるクラスのメソッドを実行した際のアサーションをイメージする。しかしTDDはソフトウェアをデザインしているという感覚を継続するための手法だと思う。つまりドライブ感が重要だという事だ。これはTDDを実践してきた人ならとっくの昔に気づいていることなのだが、残念なことにTDDを始めたばかりの人がこれに気づくのには時間がかかる。その理由の一つとして、先に述べたようなテストのイメージが弊害になっている点が挙げられる。

私達がxUnitの様なテスティングフレームワークを利用する際には、オブジェクトにメッセージを送信し、メッセージを受け取ったオブジェクトが該当するメソッドを実行した結果としての状態の変化をテストする。これはオブジェクトの振る舞いをテストしているということだ。単にクラスのメソッドをテストしているのではない。この違い(オブジェクト指向を始めたばかりの時にも同じような内容でつまづくのだが)に気づいてこそ、TDDが設計手法だという実感が得られる。テストファーストでオブジェクトがどう振舞えば正しいのかを先に定義してから実装コードを書くという行為が、ただあたりまえ(=設計してから実装する)の事を行っているだけだと気づいていない連中はアジャイル開発では設計を行わないといった短絡的な考えに辿り着く。あなた方はそんな連中と決して同じではないはずだ。ただTDDのマインドセットがこのような誤解を招くのならちょっと”視点変換”してBDD的にテストを書いてみたらどうだろうというのが僕の提案だ。

オブジェクトには状態がある。この状態こそがコンテキストだ。そしてあるコンテキストのオブジェクトにメッセージを送った際の振る舞いがスペックだ。これらは全てストーリーの実現(=小さなゴール)に向かっていること。BDD的なテストとはテストコードの記述スタイルでこの考え方を明示的にしただけのものだ。

あるストーリーを実現するためのタスクとしてオブジェクトがどのようなコンテキストの元でどのようなスペックを満たしていればよいかの一連の情報をマインドマップのスペックリストに落とし込む。

次にストーリー名の名前空間においてコンテキスト名をつけたテストクラスを作成する。テストクラスでは事前条件としてのSetUpメソッドでオブジェクトをある状態にすることやコンテキストの背景となるデータを準備することでコンテキストを作り出す。注意しないといけないのは、オブジェクトの状態はメッセージを受信したオブジェクトが該当するメソッドを実行した結果でしか変化しないという点。つまりSetUpメソッドではクラスのインスタンスを作成するだけの場合もあれば、特定のメソッドを呼び出してオブジェクトの状態を変化させておく場合もある。またコンテキストの背景としてテスト用データベースのテーブルにテストデータをあらかじめ挿入しておく場合などは、データの違いによってオブジェクトの振る舞いが変わるのであれば別のコンテキストとしてテストクラスを分離すること。要するに一つのテストクラス内の全てのテストメソッドは共通の事前条件から開始すること。コンテキスト=SetUpメソッドだと考えてもらいたい。

後はそのコンテキストにおいて、オブジェクトがどのように振舞えば正しいのかをテストメソッドとして定義していくだけだ。

ただし素振り重要。これは提案している僕自身も実践してみて感じていることだ。いきなり新しいことを始めてもうまくいかない。是非実際にコードを書いてみてBDD的なテストの感覚をつかんでもらいたい。そして疑問に思ったこと、感じたことがあれば気軽にフィードバックして欲しい。僕自身もまだ試行錯誤しているから皆さんからのフィードバックが助けになる。幸いにへなちょこな僕でも、自分ひとりだけの気づきより皆さんの気づきから得るものの方が遥かに大きいという事くらいは今までの経験で知っている。

フィードバックありがとうございます!