2011年6月8日水曜日

FunctionalTest の必要性

以前、 UnitTest と FunctionalTest と の違いについて、「コードが正しく書かれている事」のテストと、「コードが正しく動いている事」のテストとして対比した。

今日は、前者の FunctionalTest について例を上げて説明し、その必要性について考えてみる。

例えば、こんな問いがあるとする。

数字を受け取って平方根を返すプログラムを書いた。
ところが、平方根ではなくて二乗が返されるというバグが出た。
さて、どんなテストを書いておけば、これを防げたか。

最近 xUnit や TDD を始めたばかりの人なら、「xUnit で UnitTest を書いてカバレッジを 100%にしておけばよかったんじゃない?」なんて考えるかも知れない。

だけど、xUnit の実践経験がそこそこある人なら、それじゃ十分ではないとすぐ分かると思う。

これが単なるコーディングミス、つまり「正しく仕様を理解した上でのコードの書き間違い」によってのみ起因するバグならば、例えば 4 から 2が得られる事を確かめるアサーションがテストコード中にあるはずなので、誤りはすぐに検出される。この場合は、上の答えでもあながち間違いではない。

ところが、同じバグは単なるコーディングミスによるのではなく、「誤った仕様理解の下での意図通りのコーディング」によっても生じてくる。

例えば何かの拍子で、プログラマが平方根と二乗を勘違いして取り違えていた場合、本体コードに二乗の計算が書かれるのみならず、テストコードにも 4 から16を返すアサーションが書かれてしまうので、バグは検出されない。

平方根と二乗の勘違いなんて何だか馬鹿馬鹿しい例だが、実際のシステム開発のドメイン(問題領域)は、普通はもっと複雑だから、こうした認識ズレがバグの原因に占める割合は非常に多い。(また、上のような概念Aと概念Bの取り違えの他にも、仕様の見落としや失念、変更の連絡ミスなど、様々な事が認識ズレの原因になる。)

一般に、「要求されている仕様」と「実装者の認識」のズレから生じたバグは、テストコードにも同じ誤認を織り込んで書かれてしまっているため、本体のコーディングと連動して生産された UnitTest によっては検出できない。

この種のバクを防ぐためには、仕様を理解し責任を持っている人が作業に介在しなければならない。

仕様担当者がプログラマが書いたテスト仕様書をレビューしたり、仕様担当者自身がテスト仕様書を作ったりといった形で、「わかってる人」の意識をくぐり抜ける必要がある。上の例では、「平方根を返す」という要件を定義した人が、テスト仕様書に「4 ならば 2」という「条件 ---> 結果」のペアが含まれている事を確認していなければならない。

つまり最初の問いの答案としては、仕様が分かっている人にレビューされた仕様ベースのテスト、つまり FunctionalTest が必要ということになる。

(ちなみに、テスト仕様書の作成はコーディング前でも良いし、またテスト実施に自動化ツールを使ってもいい。ただし、ソースコードベースの DeveloperTestとは視点が全然違うことに注意する必要がある。例えば、網羅率はコードカバレッジではなく、仕様から起こしたテスト項目の実施率となる。)

====
といったような事は実はかなり基本的な事項なんだけど、かなり多くの底辺現場では理解されていない。で、「コードカバレッジが100%に近づいているのにバグが減らない。って事は、xUnitや TDD は役に立たないって事になるんじゃね?」なんて、アホな論理がまかり通るようになる。やれやれ…

0 件のコメント:

コメントを投稿