本エントリは「TDD Advent Calendar 2013」の参加エントリです。

@t-wadaさんの最近行ったTDDの講演や寄稿についてに引き続きの記事を書かせて頂きます。

僕がTDDを実践しようと思い始めてからの日は浅く、ちょうど1年くらい前からになります。
そのきっかけとなったのが、Certified Scrum Developerの研修でした。
この1年、TDDの実践を1つのテーマとして仕事をしてきましたが、一度、初心に帰って見つめなおす意味も含めて、Certified Scrum Developer研修におけるTDDで印象に残っていることをまとめてみます。

テストは1秒以内に実行可能にする

頻繁にテストを実行するため、時間のかかるテストは開発中にテストを実行しなくなる。
実行しないテストを開発者は記述しなくなる。

テストを書く領域にもよるとは思いますが、意識しないで書くと、少し時間のかかるテストを書いてしまっていることはあるかなと思います。そして、これを実現するためには、

テストでは外部アクセスしない

テストはデータベース、ネットワーク、ファイルシステムなどにはアクセスしない。

話を最初に聞いた際には、かなり強力な制約と感じました。
しかし、この1年、なるべくこの原則に沿うように試行錯誤した感想としては、理想論を言うのであれば、この原則を守るにこしたことはないと感じています。

Webシステムのフレームワークなどでテストの仕組みをサポートしているものでは、実際にフィクスチャとして、データベースにデータを格納して、それを利用したテストを書くものも少なくないと思います。
このような仕組みでテストを書いてもよいのですが、テストのセットアップが煩雑になったり、テストコードと別の場所にフィクスチャを管理する必要があったりとで、テストコードだけを見た際の表現力が下がりがちなのが、その理由です。

じゃあ、どうするということで登場するのが、

Mockを効率的に使う

研修では、JMock2やJMockitを使いました。
慣れるのにも時間がいるとは思いますが、これが非常に強力ということを強く感じました。

Mockを効率的に使うことで、テストがシンプルになり、自己完結するようになります。
また、こちらの和田卓人さんのCodeIQの記事において、「現在時刻へのアクセスを行うインターフェイスを抽出」というところで自分が書いたコードを取り上げて頂いたのですが、Mockを意識することで、オブジェクトの責務がより明確で単純になるという設計技法としてのTDDの効果も促せるのではないかなと思います。

次に、よく自分がやってしまうことへの自戒として、

熟練のクライマーは手と足を同時に動かさない

僕自身、「テストコード実装」→「プロダクトコード実装」→「リファクタリング」というサイクルの中で、リファクタリングの際に、よくテストコードとプロダクトコードを同時に修正してしまいます。
そして、よく意識が発散して、破綻します。

今は現状のテストコードで、プロダクトコードのリファクタリングをしているのか、あるいは、プロダクトコードが完成したから、テストコードのリファクタリングをしているのか、それを明確に意識すべきですね。

また、これと関連して、

プロダクトコードとテストコードではリファクタリングの意識が少し違う

基本的には質の高いコードを保つという意味では、プロダクトコードとテストコードにリファクタリングの違いはないです。ただし、目的が違うコードなので、質の意味が違います。

実際に研修では、ある日にコードの重複があるから、リファクタリングしなきゃいけないよという指摘を受け、それを踏まえて、コードの重複をどんどん削除しました。テストコードにも、複数のテストケースで共通するような初期化のコードがあったので、それを一箇所にまとめました。
すると、翌日、頑張って重複を除去してくれたのは分かる。でも、このテストの初期化の部分のテストコードは、結果の検証と対応しているから、の敢えて重複を許容することで、テストコードの意図が明確になるという指摘をもらいました。

以上、研修のテキストを見ながら、思い出しつつまとめてみました。
どれも基本的なことだとは思いますが、何かの参考になれば幸いです。

次は、blacさんのMSTest‐Windows ストア アプリ開発の暗黒大陸になります。