テスト駆動開発のススメ

テスト駆動開発のススメ
第8回
しばしおさらい
前回はデバッグの手法に関するトピ
ックとして、System.Diagnostics名前
Level
1
2
3
4
5
Technology Tools
Visual Basic
Visual C#
Visual C++
SQL Server
Oracle
えぴすてーめー
空間に定義された Debugおよび Tra
カくなっていささかうんざり、かもし
ce の使い方を紹介しました。両者の
れません。けれど一旦テストを書い
Writeメソッドで 処理の進行状況を逐
てしまえば 以後は常にテストに守ら
一レポートさせることができますし、
れた状態を維持しながら変更/拡張
Assertメソッドをうまく使えば「何か
できるわけで、決して無駄にはなら
ヘンなことが起こった」ことを直ちに
ないはずです。ちゃんと動くアプリ
知ることができます。デバッグで肝要
ケーションを作りたいならテストは不
なのは原因に極力近いところで現象
可欠であって、ならば書き上げてか
を捕まえることです。原因から遠く
らテストするより、もっと早期にテス
離れたところで 現象を捕まえると、
トを用意して設計/実装にも活用し
そこから原因を絞り込むのに余計な
ちゃえってわけね。
労力を費やすことになります。
加えてUnit Test Frameworkのひと
つ、NUnitを使った単体テスト、そし
てTDD(Test Driven Development:
実装とインターフェイ
スの微妙なカンケイ
Access
テスト駆動開発)についてそのあら
アプリケーションの構築は建築や
ASP.NET
ましを述べました。全部書いてから
機械と似たところがあります。原料
Other:
テストしバグを潰すのではなく、先に
から部材を作り、それを組み合わせ
テストを書き(これが書けないような
て部品を作り、部品を組み合わせて
NUnit 2.2
122
επιστημη
ら設計が甘い)
、そのテストをパスす
モジュールを、モジュールを組み合わ
Samples
るように実装することで、確実に動
せて……ってな具合に小さな/基本
この記事で取り上げたソースコードおよび
サンプルプログラムは、
http://www.shoeisha.com/mag/windev/
からダウンロード可能です。
くコードを書こうというアプローチで
的なものを組み上げて次第に大きな
す。場合によっては作りたいコード
ものへと階層化されていきます。最
そのものよりテストコードのほうがデ
終的には各部品がすべて揃い、収ま
Windows Developer Magazine
テスト駆動開発のススメ
るべきところに収まってないと正常に機能することはあ
だそうです。彼は今の仕事に手一杯で、あなたが頼んだ
りませんが、ものによっては部品がなくてもそれより上
Addが出来上がるのはしばらく後になりそう。だからと
の階層を組み上げることができます。つまり事前にきち
いってリリースしてくれるまで遊んで待ってるわけには
んと設計しインターフェイスが決まっていればいい。
いきません。Addを受け取り次第、ガチンと繋いでリリ
正しく描かれた設計図によって部品に開けられたネジ
ースしないとスケジュールを狂わせてしまいます。あな
穴の位置が決まっているのなら、その部品を組み込むモ
たが作るMultiを心待ちにしているプログラマもいるの
ジュールは(その部品がまだ完成していなくても)ネジ
だし。
穴を開けて製造工程を進めることができます。あるいは
そこで IOperationを実装し、あたかも本物のAddであ
部品、たとえばモーターがまだ完成していなくても、外
るかのようにふるまう“似非Add”を作り、それを使っ
形(インターフェイス)だけは寸分違わぬハリボテ(鉄の
てあなたの担当であるMultiの実装とテストを進めるこ
塊)を使って組み上げることができます。ただし当然の
とにしましょう。
ことながらスイッチ入れてもウンともスンとも言いませ
Multiの実装はこんな感じになりますか。
んけどね。
これとまったく同様のことをプログラミングでもでき
public class Multi {
ますし、実際にやっているわけです。
private IOperation operation;
たとえばあなたが掛け算クラス「Multi」の実装担当
public void SetOperation(IOperation op) {
operation = op;
}
だとしましょうか。Multi には実行メソッドが定義され
ますよね。
// x * yを求める
public int eval(int x, int y) {
// 必要ならば符号反転
if ( y < 0 ) { y = -y; x = -x; }
class Multi {
public int eval(int x, int y) {
// x * yを返す
}
}
// result←result + x をy回繰り返す
int result = 0;
for ( int i = 0; i < y; ++i ) {
result = operation.eval(result,x);
}
return result;
2数の積を求めるメソッドevalの実装にあたって、
「x *
y」は xをy回加えればいい、足し算クラスがあれば、そ
れを複数回呼び出すことで掛け算が実現できると考えた
あなたは同僚に足し算クラス「Add」を作ってくれるよ
}
}
うに頼みました。同僚は快く引き受けてくれましたが
「今すぐに」は無理とのこと。その代わりインターフェイ
スだけは決めてくれました。机の上に彼のメモが残され
似非メソッドを作るコツ
ています。
さて、このMultiがちゃんと動いてくれるかをテスト
/* これ使って仕事進めてておくれ! */
public interface IOperation {
int eval(int x, int y);
}
public class Add : IOperation {
…今忙しいからゴメン…
}
すべく、IOperationを実行した 似非Add「 MockAdd」
を作らなくては(mockはニセモノ/真似事の意)
。この
Mockを作るにあたって大事なことは、あくまで“見か
け上本物のようにふるまう”ことであり、中身を本物そ
っくりに実装してはいけません。この例では単に二数を
加算するだけですが、実際にはもっと複雑な処理を行な
2005 December
123