Open Source WEB

かたかたかた・・・順調にキーボードを叩いている音が内村のほうから聞こえてくる。 ひとまず、assertEquals メソッドを使って、既存のソースのテストケースを 書き始めたようだ。コードを書いて、試しに実行させて、バグに悩む、黙り込む、 という悪循環は回避されそうだ。

内村の画面を覗き込むと、たくさんのテストケースが並んでいた。

public testExecuteMba01() {
  assertEquals( true, m_fixture.Execute( "test01", "mba01", "NEW" ));
  assertEquals( true, m_fixture.Execute( "test02", "mba01", "NEW" ));
  assertEquals( true, m_fixture.Execute( "test03", "mba01", "NEW" ));
  assertEquals( true, m_fixture.Execute( "test04", "mba01", "NEW" ));
  assertEquals( true, m_fixture.Execute( "test05", "mba01", "NEW" ));
}
public testExecuteMba02() {
  assertEquals( true, m_fixture.Execute( "test01", "mba02", "NEW" ));
  assertEquals( true, m_fixture.Execute( "test02", "mba02", "NEW" ));
  assertEquals( true, m_fixture.Execute( "test03", "mba01", "NEW" ));
  assertEquals( true, m_fixture.Execute( "test04", "mba02", "NEW" ));
  assertEquals( true, m_fixture.Execute( "test05", "mba02", "NEW" ));
}
public testExecuteMba03() {
  assertEquals( true, m_fixture.Execute( "test01", "mba03", "NEW" ));
  assertEquals( true, m_fixture.Execute( "test02", "mba03", "NEW" ));
  assertEquals( true, m_fixture.Execute( "test03", "mba03", "NEW" ));
  assertEquals( true, m_fixture.Execute( "test04", "mba03", "NEW" ));
  assertEquals( true, m_fixture.Execute( "test05", "mba03", "NEW" ));
}

「よしよし、順調順調」と内村。

「ちょっと、いいかな?」とキーボードを引き寄せる森川。

テストを実行してみる森川。当然の如く、オールグリーン。テストは完了しているようだ。

「どこか問題があります?」、憮然とする内村。

テストコードはきちんと書いているつもりだし、テスト結果は自動でチェックされるから、 手作業のようなミスはない。順調にいっているのに、と文句を言いたそうだ。

森川、Eclipse 上でひとつの行にカーソルを合わせてみる。

  assertEquals( true, m_fixture.Execute( "test02", "mba02", "NEW" ));
  assertEquals( true, m_fixture.Execute( "test03", "mba01", "NEW" )); ★
  assertEquals( true, m_fixture.Execute( "test04", "mba02", "NEW" ));

「あ!?」

黙する内村。え〜と、これは、テストコードはコピペを使ったし、 結構な量のコードを書いたから、、、あの、その、、、

「すみません」

「・・・」

「あの、、、今後、気をつけます」

「いや、そういうことじゃなくて。これは、最初に陥りやすい落とし穴なんだよね」、と森川。

「落とし穴?」

「そう、はじめてテストコードを書き始めたときには、目に見えてプログラムコードが 多くなってくるし、なによりも、コードがたくさんできて進んでいるような感じに なるから、この手のミスは起こりやすいんだ」

と、森川は、再びキーボードを引き寄せて、ざっと testExecuteMba02、testExecuteMba03 を コメントアウトしてしまう。 更に、testExecuteMba01 メソッドの中もコメントアウトして、 最初の1行だけにした。

public testExecuteMba01() {
  assertEquals( true, m_fixture.Execute( "test01", "mba01", "NEW" ));
//  assertEquals( true, m_fixture.Execute( "test02", "mba01", "NEW" ));
//  assertEquals( true, m_fixture.Execute( "test03", "mba01", "NEW" ));
//  assertEquals( true, m_fixture.Execute( "test04", "mba01", "NEW" ));
//  assertEquals( true, m_fixture.Execute( "test05", "mba01", "NEW" ));
}

そして、更に、テストコードの期待値(expect)を、ture から false に変える。

public testExecuteMba01() {
  assertEquals( false, m_fixture.Execute( "test01", "mba01", "NEW" ));
//  assertEquals( true, m_fixture.Execute( "test02", "mba01", "NEW" ));
//  assertEquals( true, m_fixture.Execute( "test03", "mba01", "NEW" ));
//  assertEquals( true, m_fixture.Execute( "test04", "mba01", "NEW" ));
//  assertEquals( true, m_fixture.Execute( "test05", "mba01", "NEW" ));
}

内村に向き直って、

「スタートはここからなんだ」

森川がテストを実行すると、テストバーが赤になった。

「当然でしょ」と内村。

「そう、当然。当然に思えるんだけど、ここが大切で、わざと失敗させるのがポイントなんだ」

単体試験の場合、普通、正常系を先に進めるけど、その実行結果が正しいかどうかの チェックは、あいまいに済ませてしまうことが多い。 というのも、試験の目的が「テストが正常に終了すること」に摩り替わってしまって、 本来の「プログラムが正常に動くこと」が、おざなりにしてしまうからだ。 これは、心理的に進捗率を気にしたり、作業効率を求めたりするときに、 どうしても、進捗のあがる方の「テストが正常に〜」に向かってしまう、という 落とし穴があるためだ。

なので、

「わざと失敗させて、次に成功させるのがユニットテストの肝なんだよ」と、森川。

特に既存のコードにテストケースを付け加えるときに、この落とし穴に落ちることが多い。 既存のプログラムは、おおかた正常に動いていることが多い。 なので、ほとんどのテストケースは簡単にスルーしてしまう。

しかし、本来の目的は、ユニットテストによる結果の自動チェックを使って、 網羅しきれない「忘れ去られたバグ」を見つけることにあるから(それだけではないけど)、 スタート時点では、わざとテストケースを失敗させる方法を取る。

「そうして、少しずつテストしていく」と、コードのコメントをはずしながら 一回一回テストを繰り返す森川。

「ああ、なるほど、こういう形で一手ずつ進むと、テストコードの誤りがなくなりますね」

「そういうこと。テストコードを大量に書くのが目的じゃなくて、 正確にテストする、正確に動くプログラムに仕立て上げる、というのが目的だからね」

と、すべてのコメントを外し、間違った行を直して、森川はキーボードから手を離した。


前回:最初のユニットテスト 次回:テスト導入ふりかえり


コメントどうぞ!

Name:
Comment:

There is no comment.

このサイトは、 IPA の「平成15年度オープンソフトウエア活用基盤整備事業」 の委託事業として開発されたKahuaで試験的に運用しております。

Copyright (c) 2004-2007 株式会社タイムインターメディア About Us