SQiPチュートリアル、点と線と面と立体と四次元と

ソフトウエア品質シンポジウム(SQiP)前日に行われた併設チュートリアルに参加してきた。いくつかある講座の中から、秋山浩一氏の「体験!テスト技法:点、線、面、立体、四次元の観点で」を選んだ。なんとなく演目に引かれたのと、秋山さんとはとちぎテストの会議(#toteka)でお会いし、smalltalkの話をうかがい、今度はぜひテストのお話を聞いてみたかったので、選ばせてもらった。

今回の講演は、テスト技法を「点、線、面、立体、四次元」5つのカテゴリーに分類して説明をし、それぞれの項目に設けられた演習問題を解き、隣の人とディカッションした後に秋山さんが解答を示し、解説していく形をとっていた。RubyKaigi2010のtoRubyイベントでの参加者の感想にもあったが、手を動かすというのは、聞くだけの場合より多くの事が得られるらしい。秋山さんの講演も問題とそのディスカッションの時間があったので、講義形式に比べ理解を深めやすかったと思う。

講演を聞く前まで「点線面四次元(時間)」が何を意味するのか想像できなかったのだが、講演を聞いて、点・線・面・時間がテスト設計の考え方における視点の違い、テストケース作成技法の違いを表しているらしいことがわかった。点は一点凝視のように、ある物を正面から捉えてテストケースを創出する、もっとも一般に行われている方法である。線とは、ある軸上にいくつかの物を置き、物同士の相関を捉える方法で、境界値分析、同値分割がここに入る。面や立体では、複雑に絡んでいる因子を整理し、明らかに条件間で関連性がある場合を「面で逃さない」ように組み合わせてテストケースを考えていき、そして関連性の有無が分からない場合は、その独立性を確認するべく、対象を「立体でとらえる」ようにテストを考えていく。最後の「時間」は、状態が時間とともに遷移するような場合を網羅するテストについての話だった。

私は講演を聞きながら、このようなテスト技法を使う上で、単なるテストケースの網羅性ばかりでなく、網羅のためのコード実装を考えねばならないことに注目した。「面」のあたりで強く感じたのだが、これらの手法は実装方法、実装自体に仮定をもちこんでいるため、実装によっては抜けが出てくる可能性がある。デシジョンテーブルの圧縮では、コード上で条件分岐に質的な差が少なく、制御構造が単純なことを仮定しているように見えたからだ。
秋山さんが「実績を積むことが重要だ」と話してくれたが、私はテストに合わせたコードを作ることも1つの解決策だろうと考えた。例として、1つ1つの条件が独立している場合を考えてみると、独立した条件式を持つif文全部が表に出ていれば、各々のテストだけで済み、A,B,C,Dの組み合わせをテストする必要は無いと考えられる。


if A then procA end
if B then procB end
if C then procC end
if D then procD end
しかし、もし条件文がネストされれば、当然組み合わせテストが必要になる。

if A then
if B then
procAB
else
procA
end
end

ABの組み合わせ全てをテストすべきだが、そこで登場するのが上で書いた圧縮技法で、詳しくは書かないが、いくつかのテストケースは「必ずそうなる」としてやらないで済ますことができる。もし全ての分岐が上記のような単純さを持てば、圧縮技法によるテストケーススイートだけでも十分だと言えるのではないだろうか。
しかしやはり現実は、そう簡単ではないことは確かで、このようなコードで済む実装は無いといってもいいだろうし、無理に書けばそれだけ失うことが多そうな気がする。簡単に思いつくのがAやprocAの中身の問題で、共に構造を持っていたとしたら、そこをAやprocAといった単純なモデルで論じられるのか、AとprocA、B、procBの間に厳密に関連性は無いのかを詳しく調べないとならない。秋山さんの説明にもあったZoom in/outの話だ。簡単にZoom in/outできるのかはやはりコードに依存してしまう。

実際の現場では、コード上で怪しいと感じたら、そこを重点的にテストをすべく、コードを評価し、それに見合うテストケースを作り出していると思う。一方で、怪しいと感じたら直すという選択もある。よりシンプルなコードにリファクタリングしていくのだ。するとこれが圧縮可能なコード、つまりテストが容易なコードになっていく。もちろんシンプルなコードほど不具合が入りにくいし、テストケースも少なくなりそうだ。ということはテスト技法が有効に使えるコードセットは、そもそもテスト技法を駆使する事も無いくらいにシンプルでなければならないのかもしれない。うーーん。。。

ところで、ここまではコードとテストケースの関連を考えてきたが、ふと面や立体でとらえるテストはホワイトボックステストでいいのかという疑問を持った。開発者でないとホワイトボックスが難しいからブラックボックス、もしくはグレーボックスになるのであって、もしブラックボックスを想定してしまうと、単に技法を使うことになってしまい、その技法が正しく作用できているか判断のしようがなくなってしまう。つまりその技法を信じるしかなくなってしまうことになる。これまた何かちょっとしたパラドックスのようだが、実際はコードを書く人が嗅覚をもって怪しいところをさぐり、時にはコードを直したり、時には厳密なテストをするが、逆に嗅覚が無い人は不具合を見つけるのが不得意だったり複雑なコードを残してしまい、そこに圧縮技法が適用されると不具合が残ったままになってしまう。このことからわかるのは、まさにテストとコードを書く事は表裏一体だということだ。だから実際は厳密なブラックボックステストは存在しないか意味をなし得なくて、グレーからホワイトを行ったり来たりしているんじゃないだろうか。

以上から私が思うのは、テストケースはコードから作られるものであり、だからこそコードの洗練はテストケースの洗練につながる。一方、技法はあくまで技法であり、実績を積むことで統計的にその正しさは証明できる場合もあるだろうが、コードに依存していることに代わりは無い、ということである。
私はテスト技法については、まさにこの日初めて触れたようなものなので、この結論も表面をかじった程度のものだと思うので、少しずつでも技法を実践しつつ理解を深め、今後は開発の一部として設計とテストを考えていきたい。秋山さんのこのチュートリアルはそのモチベーションになってくれた。ありがとうございました。