その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さんのアドバイスのおかげでした。

*1:私たちはアサートコメントと呼んでいましたが、アサーションメッセージと呼ぶのが一般的らしいので、ここではアサーションメッセージとします

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スペースです