[コラム] TDD の原点 ~ Kent Beck による定義
テスト駆動開発入門
2003/9 (原著は 2002/11)
著者: ケント ベック
翻訳: 長瀬 嘉秀
ISBN: 978-4894717114
Kent Beck が提唱した TDD。 彼はどのように TDD を定義しているでしょうか?
まだ 「テスト駆動開発入門」 を読んでいない人のために、 あるいは読んだけど前書きに書いてあったことまでは忘れてしまった方のために、 おさらいしておきます。
「テスト駆動開発入門」 は、 Kent Beck が TDD について初めて書いた本です。 その本の先頭にある 「まえがき」 より引用します。 (「まえがき」 の全文は、 Amazon の 「なか見! 検索」 で読むことができます。)
自動テスト、 TDD (テスト駆動開発) と呼ばれる開発スタイルにより、 不安を少なくして開発できる。 TDD では以下を実現する。
- 自動テストが失敗した場合だけ、 新しいコードを書く。
- 重複を取り除く。
これらはシンプルな規則である。
2つの規則はプログラミングのタスクにおける順番を意味する。
- レッド ‐ 動作しないテストを少しだけ作成する。 おそらく最初はコンパイルできない。
- グリーン ‐ テストをすぐに動作させる。 そのためには、 どのようなコードでもよい。
- リファクタリング ‐ テストを動作させるためだけに作成された重複をすべて取り除く。
「RED → GREEN → リファクタリング」という手順は、 TDD の説明としていつも言われることですが、 それは引用したように上記の 2つのシンプルな規則から導かれたものなのです。
この 2つの規則に則っていない技法は、 Kent Beck が定義した TDD ではないということです。
※ なお、 2つの規則のうち最初のものを厳格に言い直したのが、 Robert C Martin の 「TDD 三原則」 (The Three Laws of TDD) です。 ⇒ 「[ブログ紹介] TDD三原則」
※ 実際の開発において、 TDD しなかった (先にテストコードを書かなかった) 製品コードが混在することを、 私は否定しません。 というより、 先にテストを書くコストが高くつく GUI などの部分は、 実際の開発の中では TDD すべきではないでしょう。 Kent Beck 自身も、 まったく TDD しないこともあると明言しています (⇒「[記事紹介] InfoQ ~ Kent Beck氏、 ごく短期のプロジェクトではテストを省略することを提案」)。 TDD は手段であって、 目的ではありません。
ところで、 ひとつめに引用した訳文の「TDD では以下を実現する」 という表現はよくわかりませんね。 引用部に該当する原文も引用しておきます。 (画像で赤く塗った部分)
Without taking too much counsel of our fears, here's what we do: we drive development with automated tests, a style of development called Test-Driven Development (TDD). In Test-Driven Development, we
- Write new code only if an automated test has failed
- Eliminate duplication
These are two simple rules,
訳本の 「以下を実現する」 に当たるのは、 原文では "we" のみです。 この we は、 直後の 2つのルールの主語です。 「実現する」 というより、 「実行する」 ですね。
私なりに翻訳しなおしておきます。
不安を抱えたまま考え込みすぎることなく(*1)、 我々が行うこと: 我々は、 自動テストによって開発を駆動する。 (それは、) テスト駆動開発 (TDD) と呼ばれる開発のスタイル。
テスト駆動開発において我々は、
- 自動テストが失敗している場合に限り、 新しいコードを書く。
- 重複を取り除く。
これらは 2つのシンプルな規則だ。
(*1) "take counsel of my pillow" (自分の枕と相談する) というのが 「一晩寝てじっくり考える」 という意味なので、 そこから類推して "taking counsel of our fears" を 「不安を抱えたまま考え込む」 と訳してみた。
( 追記 )
「テスト駆動開発入門」 の Part 1 「Money オブジェクトの例」 では、 実際に即して TDD の技法が説明されています。 その中で、 最初のルールを破ってテストを書かずに製品コードを書く例が、 3箇所でてきます。 (ざっと読み返して探しただけなので、 もう少しあるかもしれません。)
参考までに、 引用しておきます。 (強調筆者)
まず、 Part 1 の扉 (p.1) に、 逸脱する例が含まれていることが予告されています。
Part 1 では、 テストによって完全に駆動される典型的なモデルコードを開発していく (学習上の目的で脱線する場合を除く)。
ひとつめ。 p.24 で、 製品コードをごっそり (テストを通す以上のコードが含まれている) コピペしてテストを通してしまった後、 p. 29。 (後付けでテストを書く例)
コードをコピーする際に犯した罪が重くのしかかってきた。 コードを変更する前に、 最初からそこに存在すべきであったテストを作成する。
ふたつめ。 p.47。 (テストを省略する例)
テストのないコードである。 そんなことができるのだろうか。 コーディングの前に、 toString() に対するテストを作成することもできた。 しかし、 以下の理由でテストは省略した。
- 画面上で結果を見る寸前である。
- toString() は、 デバッグ出力用にだけ使用されるため、 失敗するリスクは低い。
- 既にレッドバーが表示されているので、 その場合はテストを追加しないようにしたい。
「テストのないコードである。 そんなことができるのだろうか。」
原文は "Code without a test? Can you do that?" (テスト抜きのコード? できるの?)。
これは、 「TDD のルールではそんなことはできないはずだ。 なぜそんなことをして良いのか?」 という意味合いでしょう。 TDD のルールを持ち出さなければ、 テスト抜きのコードが存在したって当たり前なのですから。 それに対して、 先にテストを書かなくても良いと判断した理由が述べられています。
最後は p.69。 (リファクタリング中にクラスを追加する例)
equals() と hashCode() を実装しなければならない。 これに対するテストは作成しない。 それは、 リファクタリングの中にこのコードを書いているためである。 リファクタリングの効果を実現し、 テストがすべて動作すれば、 コードは機能していると予想する。
この例は、 私はちょっと不安になります。 私ならテストを書くか、 時間が無ければ TODO コメントでテストしなかったことを書き残すでしょう。
| 固定リンク
「*コラム」カテゴリの記事
- [コラム] TDD のパターン: Assert First(2012.02.09)
- [TDD Advent Calendar jp: 2011] TDD とアジャイルを支えるバックボーン #TddAdventJp(2011.12.25)
- [コラム] TDD の原点 ~ Kent Beck による定義(2011.12.13)
- [コラム] TDD は止めて、 DbE (例示による設計) と呼ぼう!(2011.11.03)
- [コラム] NUnit の CollectionAssert で、 配列やリストを比較・検証する(2011.10.31)

コメント