Software Testing
News
Forum
Symposium
Columns
Articles
Readings
Research
Tools
Companies
C.S.T. FAQ
Nishi lab.
"テストマネジメント・テストプロセス" カテゴリのアーカイブ
テストのフェーズ

テストの計画を立てる時の第一歩は、テストのフェーズを決めることです。それなりの規模のシステムに対して、デバッガ上で動かすテストから本番環境での負荷テストまで、あらゆるテストをごっちゃにして行おうとすると、並みのマネジャーでは計画通りにいきません。それどころか、破綻してしまいます。すべからく仕事を上手に行うためのコツは、似たような仕事をまとめて行うことですね。

テストのフェーズで最も有名なのは、単体テスト、結合テスト、システムテスト、受け入れテストの4つのフェーズです。Boehm御大が1979年に書いた"Guidelines for Verifying and Validating Software Requirements and Design Specifications"という論文が初出でしょうか。

単体テストは、モジュールを対象としたテストです。C言語では関数、Javaではメソッド(もしくはクラス)、Pascalでは手続きのレベルですね。モジュールとして詳細設計し実装したロジックのバグを検出します。主に使う手法は、制御パステストや境界値テストです。データフローパステストを使う場合もあるかもしれません。ほとんどの場合、テストを実施するのは開発者になります。最近はテストファーストでテスト設計を行いますね。

結合テストは、モジュール間のインターフェースや組み合わせを対象としたテストです。C言語などではモジュールの呼び出しや戻り、Javaなどではメッセージのやり取りになります。モジュール間のインターフェースに食い違いがあるバグや、(単一のモジュールでバグが見つからないのに)複数のモジュールを組み合わせた時にだけ見つかるバグを検出します。モジュールを順次一つずつ組み合わせていくインクリメンタルテストという手法や、いきなり全てモジュールを組み合わせるビッグバンテストという手法が代表的です。もっともビッグバンテストが推奨される場合は、ほとんどありませんが。

構造化設計を用いている場合は、モジュール構造図の最上位、すなわちC言語におけるmain関数から組み合わせていくトップダウンテストや、デバイスドライバなど最下位のモジュールから組み合わせていくボトムアップテスト、両方同時に行うサンドイッチテストなどの方針で進めていきます。オブジェクト指向設計を用いている場合は、メッセージシーケンスにしたがって組み合わせたり、スレッドごとに組み合わせていきます。単体テストと同じように、開発者がテストを実施することがほとんどです。

システムテストは、全てのモジュールを結合した一つのソフトウェア(ビルド)を対象としたテストです。負荷をかけて初めて発生するバグ、デバイスやOS、他のソフトウェアなどとの組み合わせで発生するバグ、(単一の機能にバグが見つからないのに)複数の機能を組み合わせた時にだけ見つかるバグなどを検出します。もちろん単に機能が動かないというシンプルなバグも見つけなければなりません。また性能や操作性、セキュリティ、障害発生時のふるまいなどの評価も行います。開発者がテストを実施する場合もありますが、テストチームが担当することもありますね。仕様書を字面通り確認すればよいわけではなく、暗黙の仕様によって開発者が見落としている状況や、いかにもバグが発生しそうでユーザが操作してしまいそうな状況を想定できるか、が腕の見せどころです。

受け入れテストは、システムテストを通過したソフトウェアで問題ないかどうか、をユーザがチェックするテストです。検収と呼ばれることもありますね。ユーザ側で厳しい検収基準を用意していることもあれば、何となくユーザが触ってバグが出なければOKといった場合もあります。開発側(もしくはテストチーム)で用意したテスト項目でバグが無いことを、ユーザが監査するだけかもしれません。契約形態や作業の実態によって千差万別です。本番環境や実データでテストする場合は、並行で、または事前に移行作業が必要です。受け入れテストを実運用で行う時は、運用テストという名前で呼ばれることもあります。またパッケージソフトウェアや組込みソフトウェアの場合は特定のユーザがいない場合がありますので、サンプルのユーザ(βテスター)に頼むこともあるでしょう。

こうしてテストを複数のフェーズに分けると、なぜ混乱しないのでしょうか。それは、一度に多くの視点からテストを考えずに済むからです。各モジュールのロジックのバグを考えながら、負荷をかける環境を準備しつつ、操作性を評価するそばで、ユーザに受け入れテストをしてもらうタイミングを検討しなければならない状況を想像してみて下さい。それぞれの作業はおざなりになってしまいますね。人間は、一度に雑多な視点でモノを考えることがあまり得意ではありません。そのため似たような視点ごとにフェーズ分けを行い、一度に考える視点を絞ることで、テストの質を向上させるわけです。

視点を絞ると、網羅的なテストが楽になります。一度に雑多な視点で考えようとすると、どうしても一つ一つの視点できっちり考え抜くことが難しくなります。そのため網羅的なテストをしたつもりでも、テストに漏れが生じてしまいます。

またフェーズ分けによって、バグの切り分けコストも減少します。単体テストや結合テストをせずに全てシステムテストでまかなおうとすると、バグが見つかっても原因の特定に時間がかかってしまいます。例えば負荷テストを行ってバグを見つけたとしても、単なるロジックのミスなのか、モジュールのインターフェースがおかしいのか、メモリリークを起こしたのか、など原因の候補を一つ一つ切り分けていかねばなりません。しかしきちんとフェーズ分けを行うと、ロジックのミスは単体テストで全て潰しており、モジュールのインターフェースは結合テストで全てチェックしているはずです。したがって負荷のみに起因するバグだと絞り込むことができ、時間を節約することが可能になります。

テストマネジメントの面では、マイルストーンが決めやすいというメリットがあります。フェーズ分けを行うことで、特定の視点によるテストを一つのフェーズのみで実施するようにすると、マイルストーンをそのテストが完了したかどうかという基準にできます。フェーズ分けをしないと、どこにマイルストーンを定めてよいか、を判断するのが難しいですね。どうしてもズルズル進んでしまい、進捗管理も難しくなってしまうかもしれません。

フェーズ分けで気を付けておかねばならないのは、単体テスト・結合テスト・システムテスト・受け入れテストという4つのフェーズが、必ずしも自分の組織に合っているとは限らない点を理解しておくことです。組織によっては、単体テストの前にコードインスペクションのフェーズを設けた方がよいかもしれませんし、結合テストの後に内部状態遷移など設計に着目したテストのフェーズが必要な場合もあります。システムテストの前に機能テストというフェーズを置いている組織もあるようです。自分の組織では、どんなソフトウェアを、どんな作り方で開発しているか、をしっかり考えて、自分の組織にあったテストのフェーズを確立し、継続的に改善して下さいね。

投稿者 nishi : June 29, 2004 | コメント (0) | トラックバック
スモークテスト

テストの進捗を妨げる最大の原因は何でしょう。操作ミスをしてしまい、テストケースどおり実施できないことでしょうか。テストツールが使いこなせないことでしょうか。それとも担当者が失踪することでしょうか。

多くの組織でテストケースが消化できない最大の原因は、テスト対象のソフトウェアにバグが多すぎることです。テストをする度にバグが発生していては、いつまで経ってもテストが終わりません。試しに、バグの発生しない(OKの)テストケースと、バグの発生する(NGの)テストケースの両方について、テストケースあたりの実施時間を測定してみて下さい。圧倒的にNGの場合の方が時間がかかるでしょう。

NGテストケースの方が実施時間が長いのは、現場にいらっしゃる方なら肌でお分かりのことと思います。少なくとも不具合報告書(バグ票)を書く時間はかかりますね。OSごと落ちてしまうバグの場合は、再起動の時間がかかります。ファイルやDBの中身を壊してしまうバグが発生すると、テスト環境を全て初期状態に戻さなくてはなりません。気の利いたテスト技術者であれば、バグの切り分けを行うために、似てるけど異なる機能やパラメータ、操作手順で再テストするでしょう。もしかしたらテスト仕様が曖昧で、開発者に電話をかけなくてはいけないかもしれません。再現性を確認するために再テストも必要です。もし再現性が低かったら...。

したがってテストの進捗をスムーズに行うには、バグが少ないテスト対象をテストするようにすればよいのです。え?そんなこと分かってる、そんなことができれば苦労しない、そもそもそれならテストなんて要らないじゃないか、ですって?もちろん、バグの数をゼロにすることはできません。しかし「なるべく」少なくする工夫はできますよね。

その工夫の一つが「スモークテスト」です。ハードウェアの「焼き入れ試験(違うかな?)」が語源のようですね。作ったばかりのハードウェアに電源を通してみて、煙がモクモク上がってこないかどうか確認する、というテストになります。ソフトウェアの場合は、テスト対象のビルドに対してテストを開始する前に、簡単なテストを行うというものです。テスト開始資格審査と呼んでもいいでしょうし、「テスト側受け入れテスト」と呼ぶこともできます。

内容はとても簡単です。最も重要な機能や、過去に致命的なバグを起こした機能を中心に、短時間でできるテストを抜き出しておき、ビルドがテストチームにリリースされたら、ササッと実行するのです。テストプロセスに依存しますが、短ければ30分~2時間、長くても半日~1日程度で終わるようなテスト項目に絞っておきます。また凝ったバグ票は書く必要がありません。チェックリストがあれば十分でしょう。

なぜスモークテストは有効なのでしょうか。開発プロセスがきちんと機能しており、整然と管理されているプロジェクトであれば、それほど効果はないでしょう。スモークテストが有効なのは、混乱しているプロジェクトです。混乱しているプロジェクトでは、構成管理のミスによって先祖返りが起きたり、十分な数のバグが潰される前にビルドがどんどんリリースされたりします。こうしたプロジェクトでは、ビルドリリースの度に、テストチームが以前指摘したはずの不具合を検出したり、重要な機能に致命的なバグがあって他の機能のテストができなくなったりします。そこで、必要最低限の品質が確保されているかどうかをスモークテストでチェックすることにより、本来不必要なテストの遅延を防ぐのです。

またスモークテストを始めることで、ビルドリリースのタイミングを整えるきっかけができます。混乱しているプロジェクトではテストチームの都合を考えずにビルドリリースが行われるため、テストしたばかりの機能に手が入れられて再度ビルドがリリースされてしまったりします。1日に3回もビルドリリースされるプロジェクトもあります。こうなると、テスト結果が無効になってしまい、同じテストケースをビルドリリースの度に実施しなくてはならなくなってしまうのです。とてもムダですね。スモークテストをテスト側が行い、その時期をテストチームが指定すれば、開発チームにビルドリリースを我慢してもらうことができますので、落ちついてビルドごとに品質を安定してもらうきっかけになります。

スモークテストはビルドリリースの度に行うので、テストツールによる実施の自動化が効果的です。組織によっては、ビルドの直後に自動でスモークテストを実施し、スモークテストでNGが出たらビルド失敗とみなすところもあります。こうしておけば、テストチームが時間を割く必要はありません。

自動化しなくても、スモークテストのテストケースを開発チームに提示しておき、ビルドリリースの際に開発チームに実施してきてもらっても構いません。テストチームは、ビルドごとに開発チームの実施したスモークテストの結果のチェックリストを確認するだけです。これも大げさなドキュメントは要りません。

やや高等な技としては、開発チームに提示したスモークテストを、ビルドごとに少しずつ高度にしたり、数を増やすというテクニックがあります。スモークテストは開発チームにとって「当たり前に動くはずの」ハードルばかりです。ハードルを少しずつ上げていくことで、開発チームの品質意識を向上してもらうのです。致命的な不具合が発生したテストケースを中心に増やしていくとよいでしょう。また自動化を行っている場合であれば、数を増やすのも難しくありません。

スモークテストは、通過して当然のテストです。スモークテストに何度も失敗するようなプロジェクトは、非常にまずいプロジェクトだと認識するようにして下さい。そもそも仕様変更が多かったり、設計に必要な考慮事項が不足していたり、プロジェクトマネジメントがメタメタだったりします。プロジェクトが終わったら、またはプロジェクト進行中に、スモークテストの様子を確認してプロジェクト全体を見直し改善するようにしましょう。スモークテストのせいで開発チームとテストチームが対立するようなことは、絶対にないようにして下さいね。

投稿者 nishi : May 16, 2004 | コメント (0) | トラックバック
Powered by Movable Type
Copyright © 2003-2004 Yasuharu NISHI, All rights reserved. 027331