突っ走り書き

見せるほどのものでは..

アサートファーストでテスト駆動開発

このエントリは Advent Calendar 2013 4日目の記事です.
前日のエントリーは,comuttさんのvim + py.test で TDDでした.

アサートファースト

このエントリでは「テストコードの書き方」,特に,

  • テストコードの中身をどの順番で書き進めるか

についてまとめます.
TDDと言えば「テスト・ファースト」ですが,Kent Beck は,さらに「アサート・ファースト」によるコーディングを提案しています.

アサートをいつ作成するべきなのか. → 最初に作成するべきである.

ーKent Beckテスト駆動開発入門ー


では,次のテストメソッドを書くとき,どのような順番でコーディングするのがいいでしょうか?

public void add_return105() {
    Money sut = new Money(100);
    Money other = new Money(5);

    assertThat(sut.add(other), is(100 + 5));
}

アサートファーストを採用すると,次のような順番で書きます.

// 3: テスト名を付ける
public void add_return1() {
    // 2: assert文に必要なオブジェクト(sut/other)を作成
    Money sut = new Money(100);
    Money other = new Money(5);

    // 1: 実現したい機能をassertで表現
    assertThat(sut.add(other), is(100 + 5));
}

実際にコーディングするときは,次のようなイメージで実装します.

  1. まずはテストしたい仕様をassert文で書きます
  2. つぎにassert文に必要なオブジェクトを作ります
  3. 最後にテスト全体の内容を確認しながらメソッド名を決めます

IDEの助けを借りる

先の順番にコーディングすると,assert文を書く時点でsutが宣言されていないため,IDEメソッド名を補完してくれません.
そこで,現代っ子は先にsutを宣言するのがベストかと思います.

// 4: テスト名
public void add_return1() {
    // 1: テスト対象のオブジェクトを作成
    Money sut = new Money(100);
    // 3: assert文に必要なオブジェクトを作成
    Money other = new Money(100);

    // 2: sut がみたす仕様をassertで表現
    assertThat(sut.add(5), is(100 + 5));
}

プログラマの負担を軽くすることがすべて

テスト駆動開発のメリットは,プログラマの負担を軽減できることです.
一度に複数のことを考えるのは,(できたとしても)楽ではありません.
テスト内容をぼんやりとイメージしながらコーディングするのではなく,assert文という明確な目的を何よりも先に設定することで,頭の中をクリアに保てます.
テストに導かれてプロダクションコードが生まれるように,テストコードはassert文に導かれるべきです.
アサートファーストで気楽にプログラミングをしましょう!

Advent Calendar はまだまだ続きます

明日,12月5日の担当は2回目の登場 setoazusa さんです.
よろしくお願いします.