ソフトウェアテスト。設計通りにソフトウェアが機能しているかを確認する、大事なプロセスです。
一方、テストでなにをどこまでやればよいの?判断にとても悩むプロセスでもあります。
そんなテストへの指針を示すのが、「ソフトウェアテストの7原則」です。
ソフトウェアテストの7原則とは
ソフトウェアテストの7原則(7 Principles of Software Testing)とは、ISTQB(国際ソフトウェアテスト資格認定委員会)によって収集および確立されてきた原則です。テストの核心として認識されています。
テストは欠陥があることしか示せない
Testing shows the presence of defects
全数テストは不可能
Exhaustive testing is impossible
早めにテスト
Early testing
欠陥は偏る
Defect clustering
殺虫剤のパラドックス
Pesticide paradox
テストはコンテキスト次第
Testing is context dependent
エラー不在という誤信
Absence-of-errors fallacy
順番に見ていきましょう。
テストは欠陥があることしか示せない
『テストしてエラーが出る。だから、そのソフトウェアにはバグがある』…これはもう明確な事実です。
では、『テストしてエラーが1つも出ない。だから、そのソフトウェアにはバグがない』…とはなりません。
何万件のテストを重ねたとしても、まだやっていない他のテストをすればエラーになる、その可能性は無くなりません。ソフトウェアにバグがないことの証明は「悪魔の証明」と同じです。
ソフトウェアにバグがないことを証明するのは、不可能なのです。これがソフトウェアテストで認識すべき、重要な大前提になります。
クライアントとの契約の際も、「バグがないこと」を完成条件に定義してはいけません。できるのは「決められたテストを全てクリアする」と定めるところまでなのです。
全数テストは不可能
全数テストとは、「ありとあらゆる条件をすべて網羅したテスト」です。
ソフトウェアとは、突き詰めれば、インプットに対してアウトプットを返すこと。なら理屈で言えば「可能性のあるすべてのインプットをテストすれば、すべての動作が確認できる」ことになります。
でもこれは、事実上不可能です。たとえば「名前を入力するテキストボックス」を考えましょう。入力のパターンは?「鈴木」「田中」「高橋」「(空白)」「a」「b」「c」…。パターンは無限に考えられます。
すべてのパターン(=全数)をテストするのは、不可能なのです。これが「ソフトウェアにバグがないことを証明するのが不可能である」ことの最大要因です。
ではどうするか?できるだけ網羅性を失わないように、テスト条件を絞ります。例えばこのような考え方。
- 同値分割(Equivalence Partitioning Testing) 結果が同じとなる条件でグループ分割し、代表値でテスト
- 境界値分析(Boundary Testing) 同値分割グループの境界値と前後の値でテスト
得られる結果のバリエーションを網羅するように、テスト条件を決定する必要があります。
早めにテスト
ソフトウェアの開発ライフサイクルは、一般的にこのように進みます。
要件定義 > 設計 > コーディング > ユニットテスト > 結合テスト > システムテスト…
ユニットテスト、結合テスト…と進むにつれ、多くのモジュールを組み合わせてテストすることになります。
ユニットテストのときは、バグ修正は簡単です。そのモジュール1つを直せばよいのですから。
テストが進むと、バグ修正のコストが格段に上昇します。組み合わせたモジュールすべてに影響が及ぶ可能性があるからですね。
なので、同じバグなら、可能な限り早めに取り除いたほうがよいのです。
「よし、ユニットテストでできるだけバグを取り除こう…」いやいやそれでは足りません。テストはもう、要件定義の時点から始まります。
矛盾した仕様、複雑なメッセージ、存在しないデータ…。いろいろな欠陥の芽が見えています。そこで欠陥が除ければ、そもそもコーディングで欠陥が埋め込まれることもないわけです。
欠陥は偏る
ソフトウェアのバグは、さまざまなコードに万遍なく発生する、ということは、あまりありません。
たいていの場合、バグの発生する箇所はどこかに偏りをみせます。これは、実際にテストをしたことがあるなら、経験則的に分かるでしょう。
そのソフトウェアの中でも、複雑なアルゴリズム、多くのイベント制御するインターフェイス、そのようなコアな処理のモジュールに、バグは集中します。
これは、ソフトウェアテストにおける「パレートの法則」と言えます。
テストの中で、バグが発生するモジュールの傾向を見極め、テストリソースを集中させる。そうすれば、エラーの解決が早まります。
殺虫剤のパラドックス
農作物に昆虫がつかないように、殺虫剤を撒きます。何度も繰り返し使用すると、撃退しようとしている昆虫が殺虫剤に対して免疫を獲得し、効果がなくなってしまいます。
この現象が、ソフトウェアテストにも当てはまります。同じセットのテストを繰り返しても、新しい欠陥を発見するのには役に立ちません。
あるソフトウェアを、改修するケースを考えましょう。
- 既存テストクリア済のモジュールを、改修します。
- 担当プログラマーは、これまでのテストも経験済。
- なので、どこがどうなると、そのテストがエラーになるか知っています。
- 当然、テストがエラーにならないよう、気をつけて改修します。
- 既存テストケースでは、そうそうエラーが起こりません。
- でも、新しく改修したところには、このテストの効きめがないのです。
ソフトウェアに修正や改修を加えるなら、テストケースも一緒に見直す。そうしないと、テストの効果が落ちてしまいます。
テストはコンテキスト次第
コンテキストとは「文脈、前後関係、事情、背景、状況」といった意味です。
コンテキスト次第というのは、つまりこういうことです。どのようなテストが必要かは、そのソフトウェアの目的や背景に依存する。
スマホアプリ、クラウドマイクロサービス、ロボット制御ソフトウェア…それぞれの特性に応じて必要なテストは変わってきます。どんなソフトウェアにも適用できるテストの種類や方法は、ないのです。
エラー不在という誤信
ソフトウェアテストに関して、プログラマーがつい勘違いしがちなこと。それは、
と思ってしまうこと。
大変なテストを乗り越え、ついにエラーをなくした瞬間。プログラマーは無常の達成感に包まれるでしょう。しかし忘れてはなりません。ソフトウェアは、エラーを0にすることが最終目標ではないのです。
考えてみてください。あなたがディーラーで車を買おうとしたときに、
そんなこと言われて、喜びますか?
ユーザーにとって、エラーが0なのは、至極当たり前のことなのです。
使いやすい、速い、きれい…ユーザーはそういった、機能定義としては現れない、非機能要件を求めます。それを確認するには、ユーザーと一緒にソフトウェアをテストしたり、ユーザビリティを初期のプロトタイプでテストしたりといった方法も考えられます。
まとめ
ソフトウェアテストは、難度の高い作業です。それは、
- 完璧なソフトウェアを作りたい
- でも完璧なテストはありえない
という、相反する命題に答えを出す必要があるから、といえるでしょう。
完璧なテストはない、という事実を受け入れつつ、どうすれば限られたコストで最大限の効果を出すか、が重要です。
「ソフトウェアテストの7原則」を意識しながら、「完璧なソフトウェア」という、崇高の頂を目指しましょう。
コメント