仕事でTDDを使って開発することになったので改めて書籍「Clean Craftsmanship 規律、基準、倫理 (Robert C. Martin 著, 角 征典 訳 : 以下 参考書籍)」を読み直し自分用にまとめてみる。
TDDとは
TDD(テスト駆動開発)。テストを書くことによって開発を進めていく開発手法。
TDDの本質は、以下のことを行うための規律をもたらすこと。
- 信頼できるテストスイートを作成し、リファクタリングの作業や、デプロイ可能かどうかの判断ができるようにする。つまり、テストスイートをパスしていれば、システムをデプロイできる。
- 適切に分離された本番コードを作成し、テストやリファクタリングを可能にする。
- 極端に短いサイクルのフィードバックループを作成し、プログラムを書くリズムと生産性を安定させる。
- テストコードと本番コードを相互に分離させ、変更があっても両者に複製することなくメンテナンスできるようにする。
プロダクトコードができた時は、テストが揃っている時であり、仕様が整理されている時であり、そしてデプロイできる時でもある。テスト自体が分解された仕様であり、そのテストを通るコードが書かれているからだ。
4つの法則
第一の法則
テストを書くまでは本番コードを書いてはならない。本番コードがないためにテストは失敗する。
第二の法則
失敗するテストやコンパイルできないテストを必要以上に書いてはならない。失敗を解決するには本番コードを書く。
第三の法則
失敗しているテストを解決する本番コードを必要以上に書いてはならない。テストがパスしたら、追加のテストを書く。
第四の法則
リファクタリング
いわゆるレッド→グリーン→リファクタリング。まず失敗するテストを書き(テスト結果はレッド)、そのテストを通すためのプロダクトコードを書き(テスト結果をグリーンに)、そしてテストが通ることを維持しながらプロドクトコードのリファクタリングを行う。
実践してみて
TDDで開発をしようとすると、自ずとテストしやすいコードを意識するようになる。テストしやすいコードを意識すると、実装しようとする機能をできるだけ細かく分解し、シンプルな処理や振る舞いに落とし込むにことになる。慣れないうちはここで苦戦する(何なら今している)。
大抵の場合、要求される仕様の粒度の方が大きいからだ(例えば、”ボタンを押すと集計結果一覧が表示される”のような)。ここですぐ粒度が大きいままの仕様のテストを書こうとすると途端に思考が停止する。あるいはなんとかテストを書いても、途中の処理が多すぎたりしてなかなかグリーンまで辿り着かない、ということが起こる。
仕様に対して機能を実装するとき、実際は小さな処理や部品を組み合わせていくことになる。テストも小さな処理や部品のほうが当然書きやすい。しかし、粒度の大きい仕様をみて、細かなそれぞれの部品の仕様に分解して整理できるようになるには工夫が必要だ。
自分の場合は、まずコメントで処理の流れに沿って概要を箇条書きにしながら、処理を分解・整理していく(まだコードは書かない)。一通り書き出せてから、細かい処理についてのテストを書く(しかも呼び出すだけの簡単なテスト)。そしてコードを書く。あとはレッド、グリーン、リファクタリングを繰り返し、一つのコメントについての処理が終わったら次のコメントに取り掛かる。これを繰り返す。
もう一つの問題として、何をどこまでテストするかと言う問題もある。これはプロジェクトの方針やチームの方針にも左右されるのでよく確認する必要がある。