特集

「テスト駆動開発」はプログラマのストレスを軽減するか?

株式会社ピーデー
川俣 晶
2003/11/08

Page1 Page2 Page3 Page4

■再びレッドへ

 この段階では、まだコードが単純すぎてリファクタリングする内容がない。そこで、次のレッド/グリーン/リファクタリングのサイクルに入っていこう。最初のサイクルが完了することは、決して、対象とするメソッドの完成を意味しない。このメソッドのテストが失敗するケースを次から次と考えて、サイクルを回す。そして、これ以上、テストが失敗するケースを思い付かなくなったとき、メソッドは完成したといえるわけである。

 さて、このメソッドが失敗するケースは山ほどある。要するに、結果が3以外になる引数を指定すれば、すべて失敗するはずである。その中の1つとして、「2+3=5」というケースをテストに追加してみよう。

[Test]
public void Plus()
{
  Assertion.AssertEquals( 3, SampleClass.Plus(1,2) );
  Assertion.AssertEquals( 5, SampleClass.Plus(2,3) );
}
「2+3=5」というテストを追加

 これをテストすると以下のようになる。

再びレッドの状態になったNUnitの実行画面
足し算メソッドは必ず3を返すため、追加したテストは失敗する。

 見事に再びレッドの状態に陥った。

■再びグリーンへ

 これをグリーンにする最も安直な方法は、この計算に対する答を直接的に書き込んでしまうことである。引数が2と3であれば、5を返せばよいのである。例えば、以下のような感じだろうか。

public static int Plus( int x, int y )
{
  if( x == 2 && y == 3 )
  {
    return 2+3;
  }
  return 1+2;
}
最も安直な方法で「2+3」にも対応した足し算メソッド

 これをテストすると以下のようになる。

再びグリーンの状態に戻ったNUnitの実行画面

 見事に再びグリーンの状態に戻った。

 しかし、このような状態に何の意味もない、と思った読者もいるだろう。こんな形でグリーンを得ても、引数の値を変えれば再びレッドに陥ってしまう。まさか、すべての引数の組み合わせに対して、if文を並べるわけにもいかないだろう。

 もちろん、そんなことにはならない。テストするケースは2つまでしか増えない。なぜなら、同じ処理が2つあれば、リファクタリングの対象になるためである。

■リファクタリングの実施

 ここでいよいよリファクタリングである。

 このソース・コードには重複処理が2つある。1つは、+演算子を使った足し算が2回あること。もう1つは、returnが2つあることである。この重複を取り去ってしまおう。

 まず、定数を直接式に書いているから、複数の+演算子を書かねばならないわけである。ならば、変数を使って足し算を行えばよい。変数を使って足し算をすれば、場合分けのif文も不要になる。途中の経過は省略して、最終形を示すなら、以下のように書き換えることができる。

public static int Plus( int x, int y )
{
  return x+y;
}
リファクタリングを行った足し算メソッド

 これをテストすると以下のようになる。

リファクタリングの成功を示すNUnitの実行画面
この画面は、テストの結果を変えることなく足し算メソッドをリファクタリングできたことを示す。

 グリーンのバーが、テストの結果を変えることなくリファクタリングできたことを示している。

 ここまできたら、次は、テストの方を見てみよう。ここにも重複があるのが分かるだろうか。

Assertion.AssertEquals( 3, SampleClass.Plus(1,2) );
Assertion.AssertEquals( 5, SampleClass.Plus(2,3) );

 ここで、2つのケースは同じことをテストしているのである。少し前までは、この2つのケースは異なる結果を示していた。しかし、いまはもう、同じ結果しか示さなくなった。これも重複といえるので、片方を取り除くことができる。

[Test]
public void Plus()
{
  Assertion.AssertEquals( 3, SampleClass.Plus(1,2) );
}
不要なテストを取り除いたテスト・メソッド

 これを実行してもグリーンが維持され、テストは依然としてパスしていることが示される。

 これ以上、リファクタリングできる個所を見つけられなかったので、リファクタリングは完了である。

 このように、2つのケースからリファクタリングを通して汎用的なコードを得るテクニックを、TDDでは「三角測量」という。足し算メソッドのように明白な実装がすぐ分かる場合はあまり有益ではないが、入出力は明らかなのに内部ロジックが容易にイメージできないメソッドを実装する場合には有益な手順である。

 そして、これ以上このメソッドのテストが失敗するケースを考えることができなかったので、これで足し算メソッドの開発は完了となる(本当なら、オーバーフローやアンダーフローのテストも考えた方がよいと思うが、今回は省略する)。


 INDEX
  [特集]「テスト駆動開発」はプログラマのストレスを軽減するか?
     1.新しいソフトウェア開発技法へチャレンジできるか?
     2.レッド/グリーン/リファクタリングの三拍子
   3.再びレッドとグリーン、そしてリファクタリング
     4.どんなときにテスト駆動開発を採用すべきか
 


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間