Kent Beck による著書「テスト駆動開発」より、TDD の概要をまとめた。
業務でTDDを行っている者として、基本に忠実にプロジェクトを進めることの難しさをよく感じるので、よい機会になった。
TDD は何を可能にするか?
TDD のゴールは、「動作する綺麗なコード」を生み出すことである。
一般的なソフトウェア開発では、「きれいな」コードを目指す前に、「動作する」事の前に多くの制約が立ちふさがる。
この問題のアプローチとして、考え込む前に、自動化されたテストによって開発を推し進める。このような開発が**テスト駆動開発(Test-Driven Development: TDD)**と呼ばれる。
TDD のルール
TDD は、以下のシンプルな二つルールのみである。
-
自動化されたテストが失敗したときのみ、新しいコードを書く
-
重複を除去する。
これらのルールに従って開発を行うと、開発者が自分たちでテストを書くようになる。
また、凝縮度が高く結合度が低い、たくさんの部品で構築された設計を行うようになる(テストが書きやすいコードになっている)。
TDD のリズム
TDD は、レッド・グリーン・リファクタリングのリズムで行われる。
-
1.レッド
動作しない、コンパイルも通らないテストを書く。
頭の中で考えている挙動が、どのようなコードとなるかをテストが失敗するようにするためには、実行可能なテストとテストが動くための仮実装があるということであり、何もできていないというわけではない。 -
2.グリーン
そのテストを動作するコードを書く。
前のテストが通るようなコードを実装していく。ここでの目標は完璧できれいな解を出すことではなく、テストを通すことだ。要するに、汚いコードを気にする必要はなく、最短でグリーンなテスト結果を見ることを目指す。 -
3.リファクタリング
テストを通すために発生した重複を全て除去する。
テストに依存しないようにプロダクトコードを正しくする。変更を加えるたびにテストがグリーンとなることを確認する。もはや不要なテストは消してしまう。
TDD における実装
TDD における実装では、仮実装と、明確な実装、三角測量という 3 つの手法がある。
明確な実装
すぐに頭の中の実装をコードに落とす。
すべてが上手く行っており、書くべきコードを把握している場合、明確な実装->明確な実装…と連続していく。
仮実装
コードでまずベタ書きの値を使い、実装を進めつつ、徐々に変数に置き換える。
明確な実装を続けている中で、予期しないレッドバーを目にした場合、仮実装に切り替える。
三角測量
よりコードが一般化できるよう、新たにテストケースを追加する。
実装方法が明らかでない場合や、テストが要件をしっかりテスト出来ているかわからない場合、よりコードが一般化できるようにテストケースを増やし、グリーンにする。
テストコードが持つ意義
テスト駆動開発は、プログラミング中の「不安」をコントロールする。漠然とした不安ではなく、問題の困難さに由来する、「見通しのつかなさ」である。
一般的なプログラミングでは、プロダクトが大きくなればなるほど、この「不安」を抱え続けることになる。一方 TDD におけるテストは、コードが動作することを保証し、「不安」を軽減してくれる。一つのテストコードがグリーンになることは、全てが動作する状態に向けて一歩前進していることがわかる。
TDD におけるリファクタリング
一般的なリファクタリングでは、プログラムの意味を変更することは推奨されない。
しかし、TDD におけるリファクタリングでは、気にすべきはすでに通っているテスト、という事になる。たった一行の変更でも、TDD においてはリファクタリングと言える。なぜなら、通っているテストが変わらず通っているからだ。
ただし、このような状態になるには、十分なテストを書いて、「観測上の等価性」を担保する必要がある。
途中で切り上げるには?
- 一人でプログラミングしている場合、最後に書いていたテストを失敗する状態にして終える。
こうしておくことで、次にコーディングに戻ってきた時に、どこから始めるべきかは明白だ。テストは中断前に考えていた事を思い出すための確かな手がかりとなる。失敗させたままにしているテストは、プログラムの現状を明らかにしているので、心を痛めるようなことではない。
- チームでプログラミングしている場合、テストを全て通る状態にして終える。
チームで開発している場合、最後に見た時からどのようにコードが変わっているか、わからないという状況が起きやすい。この場合、自信と確信がある場所から仕事を始める必要がある。そのためにも、コードをチェックインする前には、全てのテストが通ることを常に確認すべきである。
チームのルールとして、チェックイン前にテストが通らない場合、「手元の変更を捨ててしまい、初めからやり直し」するルールを設けておくと良い。このルールでは、チーム内では「早くチェックインしたい」という空気が生まれ、頻繁にコードがチェックインされ、テストが実行される事になる。