Chat (Lingr.com)
Informaiton
Daily
Column
- MySQL日本語の旅(5/1)
- アクセス向上秘伝(5/9)
- 一風変ったHaskellλ門(6/13)
- SICP Answer Book (5/31) 問題3.26追加
Zope Solution
Extra
アーカイブ
OSS案内所
Site Info
関連リンク
かたかたかた・・・順調にキーボードを叩いている音が内村のほうから聞こえてくる。 ひとまず、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" ));
}
内村に向き直って、
「スタートはここからなんだ」
森川がテストを実行すると、テストバーが赤になった。
「当然でしょ」と内村。
「そう、当然。当然に思えるんだけど、ここが大切で、わざと失敗させるのがポイントなんだ」
単体試験の場合、普通、正常系を先に進めるけど、その実行結果が正しいかどうかの チェックは、あいまいに済ませてしまうことが多い。 というのも、試験の目的が「テストが正常に終了すること」に摩り替わってしまって、 本来の「プログラムが正常に動くこと」が、おざなりにしてしまうからだ。 これは、心理的に進捗率を気にしたり、作業効率を求めたりするときに、 どうしても、進捗のあがる方の「テストが正常に〜」に向かってしまう、という 落とし穴があるためだ。
なので、
「わざと失敗させて、次に成功させるのがユニットテストの肝なんだよ」と、森川。
特に既存のコードにテストケースを付け加えるときに、この落とし穴に落ちることが多い。 既存のプログラムは、おおかた正常に動いていることが多い。 なので、ほとんどのテストケースは簡単にスルーしてしまう。
しかし、本来の目的は、ユニットテストによる結果の自動チェックを使って、 網羅しきれない「忘れ去られたバグ」を見つけることにあるから(それだけではないけど)、 スタート時点では、わざとテストケースを失敗させる方法を取る。
「そうして、少しずつテストしていく」と、コードのコメントをはずしながら 一回一回テストを繰り返す森川。
「ああ、なるほど、こういう形で一手ずつ進むと、テストコードの誤りがなくなりますね」
「そういうこと。テストコードを大量に書くのが目的じゃなくて、 正確にテストする、正確に動くプログラムに仕立て上げる、というのが目的だからね」
と、すべてのコメントを外し、間違った行を直して、森川はキーボードから手を離した。
前回:最初のユニットテスト 次回:テスト導入ふりかえり
There is no comment.