ギブスというとちょっと物々しいですが、TDDer養成ギブスは小技や小さい指針が多いです。「くせ」や「心がけ」のようなものをちょこちょこ書いて行こうかと考えています。TDDを行う/行いたい人の背中をそっと押すようなTipsであればと思っています。
その1「assertion message first促進ギブス」
第一弾のTDDer養成ギブスは、私たちが一番頻繁に使っているものから行こうと思います。名づけて「assertion message first促進ギブス」です。
JUnitのassertEqualsメソッドには、引数が3つあるものと2つのものがあり、引数3つのassertEqualsメソッドの第1引数がアサーションメッセージです*1。ここに書かれた文字列はassertionが失敗したときに表示されます。「marsのメモ(id:masanobuimai:20040826#1093492773)」や「生きてま(http://log.giantech.jp/353)」で言及されているように、アサーションメッセージは非常に重要です。なぜなら、
- テストが失敗したときに何が失敗したのかが一目瞭然
- テストの可読性が上がる。日本語のほうがやっぱり読みやすい
- テストをアサーションメッセージから書くことによって「これから何をテストするのか」が明確に意識される
からです。特に3番目の"テストをアサーションメッセージから書くことによって「これから何をテストするのか」が明確に意識される"は重要です。
しかしアサーションメッセージを書くことは結構忘れやすく、また面倒くさいのも現実です。このギブスは重要だけれども忘れやすいアサーションメッセージを書くことをちょっとだけ後押しします。
(追記) このエントリを書いた後しばらくして、私たちのチームは、テスト名そのものを日本語で書けばいいという方向になりました。masarlさんのアドバイスのおかげでした。
assertion message firstテンプレート準備
Eclipseにコードテンプレートの機能があることは多くの人がご存知のことと思いますが、このコードテンプレート機能をうまく使うとコーディングを加速することが出来るようになります。コツは、欲張らずに、ほんの少しのコードをほんの少しの手間で書けるようにすることです。
では早速テンプレートを書いてみましょう。Eclipseのメニューから、ウィンドウ→設定と進むと、設定ウインドウが出てきます。設定ウィンドウの左手のツリーからJava→エディター→テンプレートと開いていきます。すると既存のテンプレートがずらずらと出てくると思います。新規のテンプレートを作成するために、右手の「新規」ボタンを押します。すると、テンプレートの新規作成ウィンドウが出てきます。そのウィンドウにて
- 名前:ae
- Context:java
- 説明:assertEquals template
- Pattern:
assertEquals("${msg}", ${expected}, ${actual});
という内容のテンプレートを登録します。注意点は、Contextというコンボボックスでjavaを選択しておくことです(デフォルトはJavadocが選択されています)。
これで、今のテンプレートが"ae"という名前で登録され、Javaエディタの中から使用できるようになります。
いざassertion message first開始!!
サンプル用のテストクラスを作成します。ここではスタックのテストとします。
package learning.tdd; import junit.framework.TestCase; public class MyStackTest extends TestCase { }
テストメソッドをひとつ書いておきましょう。最初のテストは、作成直後のスタックのサイズが0であることをテストするものとしましょう。*1
package learning.tdd; import junit.framework.TestCase; public class MyStackTest extends TestCase { public void testDefaultStackSizeShouldBeZero() throws Exception { } }
以降テストメソッド"testDefaultStackSizeShouldBeZero"の中のみを書いていきます。
さて、テスト名が決まったらassert文を書きましょう。さっそく先程登録したテンプレートを使います。
public void testDefaultStackSizeShouldBeZero throws Exception { ae }
"ae"まで書いたところでCtrlを押しながらSpaceを押します(EmacsキーバインドではAlt + /)。すると先程登録された"assertEquals template"が選択候補に出てきますので、選択します。
public void testDefaultStackSizeShouldBeZero throws Exception { assertEquals("msg", expected, actual); }
すると先程のテンプレートの中身が出力されます。このときにフォーカスが「msg」の上に当たっているはずです。ここでまだEnterキーを押さずに、そのままアサーションメッセージを書き始めます。ここで、アサートしようとしているのは何なのかを考えて、アサーションメッセージにします。
public void testDefaultStackSizeShouldBeZero throws Exception { assertEquals("作成直後のスタックのサイズは0であること", expected, actual); }
日本語でアサーションメッセージを書いているので一回だけEnterを押して日本語変換を確定し、その後半角入力モードに戻ります。まだアサーションメッセージのところにフォーカスが当たったままのはずです。ここでTabキーを押します。すると「expected」の上にフォーカスが移動するはずです。
public void testDefaultStackSizeShouldBeZero throws Exception { assertEquals("作成直後のスタックのサイズは0であること", expected, actual); }
期待値を書き込みます
public void testDefaultStackSizeShouldBeZero throws Exception { assertEquals("作成直後のスタックのサイズは0であること", 0, actual); }
"0"を書き込んだら、まだEnterを押さずにTabを押します。フォーカスが次の「actual」に移動します。
public void testDefaultStackSizeShouldBeZero throws Exception { assertEquals("作成直後のスタックのサイズは0であること", 0, actual); }
ここで、テストしようとしている対象メソッドは何なのかを考え、"stack.size()"を書きます。
public void testDefaultStackSizeShouldBeZero throws Exception { assertEquals("作成直後のスタックのサイズは0であること", 0, stack.size()); }
まだ"stack.size()"の上にフォーカスが当たっているはずです。ここでEnterを押します。するとカーソルが行末に移動します。この後テストの続きを(stackの参照を作るところから)書いていきますが、今日のお題としてはここまでです。
これがアサートファースト、いや、「アサーションメッセージファースト」です。私たちは毎日このような方法でassertion message firstしています。
*1:この文章では横幅をケチるためにインデントを2スペースで行っています。普段は4スペースです