はじめまして

詳しくはプロフィールを見ていただければと思いますが、今回はMENTAを利用させていただくのが初めてということもあり、宣伝がてら皆さんの気が少し楽になるTipsを提供できればと思います。

TDDは「テスト駆動開発」ではない

TDDは「テストを先に書いて開発を進めていく」、ということではありません。

テスト駆動開発を世に知らしめたKent Beckは自著の中で次のように言っています。

皮肉なことに、TDD はテスト技法ではない (Cunningham の考案)。TDD は分析技法であり、設計技法であり、実際には開発の全てのアクティビティを構造化する技法なのだ。

これは権威主義を目的として引用したわけではなく、実際に著名なソフトウェアアーキテクトのビデオキャストなどを見てみると、TDDがいわゆるテストとして使われている様子はなく、システムを設計する際の補助輪として使われている様子がわかります。

それではTDDがテストのための技法でないならば、具体的には一体なにをするための技法なのでしょうか?

そもそもテストとは

それを理解するためには改めてテストという言葉の定義を明確にする必要があります。
ソフトウェアにおけるテストとは「プログラムのエラーを見つける活動」を指します。

具体的な手法としてはブラックボックステスト、ホワイトボックステスト、探索的テストなど様々なテクニックやメンタルモデルがあり、少し調べるとすぐにわかることですが、いわゆるTDDにおけるテストとはまったく雰囲気が異なることがわかります。

それでは、TDDにおける「テスト」と呼ばれていた活動は具体的には一体どのような目的で、なにを行うためにあったのでしょうか?

TDDにおける「テスト」とは「振る舞いを定義する活動」を指す

TDDにおける「テスト」とは、そのプログラム (具体的には関数・クラス・システム全体など)が、どのように動いて欲しいのかという、いわばゴールを先に宣言し、そこに向かって実装をしていく活動を指します。

例えば「商品を財布に入っているお金を消費して購入する」というプログラムがあった場合、そのプログラムには以下のような挙動が期待されます。

  • 商品の合計金額は財布にある残金を超えられない
  • 在庫が0の商品は購入することができない

もし上記の挙動が満たされるならば、例えば以下のようなシナリオが成立するはずです。

  • (成功パターン) 「前提としてお金が1000円あり、かつ一つ900円の商品が1つあるとき」 => 「その商品を購入を確定すると」 => 「購入に成功する」
  • (失敗パターン)「前提としてお金が100円あり、かつ一つ900円の商品が1つあるとき」 => 「その商品を購入を確定すると」 => 「購入に失敗する」

一方でこれらのシナリオは「もしお金が1000円で、かつ1000円の商品があった場合 (境界値)」や、「-1つの商品を購入した場合 (無効値)」のようなケースについては考慮していません。これは一般的なテストとしては不十分ですが、それでもTDDにおける「テスト」としては十分ということになります。専門用語を使えば、そのプログラムの「契約の宣言をおこなう」ことがTDDにおける「テスト」の役割です。

具体的なTDDの進め方

それでは先の例に沿って、TDDをどう進めていくのかを簡単にご紹介します。

  1. やりたいこと(ビジネス要件)を自然言語で考える (例: 「ユーザーにはシステム内通貨で商品を購入して欲しい」など)
  2. 1で洗い出したそれぞれのビジネス要件について、「Given (前提)」「When (〜するとき)」「Then (結果)」の各ステップに分割する。このように整形したビジネス要件がシナリオとなる
  3. シナリオの各ステップを再現する処理をテストフレームワークを利用して書き、後続のステップは前のステップの状態を引き継げるように工夫する。グローバル変数を使ったり、テストフレームワークが提供しているネスト機能を使うなどします。
  4. 3で定義したステップを満たす最低限の実装を書く。最初は固定の数字を返すような実装でも十分なことも多く、一つの機能に対するシナリオが増えたり、より大きな機能を作るようになると、自然と実装は充実していくはずです

以上がTDDの簡単な理解と進め方です。より具体的な方法を知りたい、TDDができているかどうか自信がないという方は、【経験者向け】コーダーの先のステップに進む方法教えますからお気軽にご相談ください。必要に応じて今はまだないプランを作成することも考えています。