正常系と異常系と準正常系

2020年1月22日その他

テストは正常系と異常系と準正常系を設計しましょう

テストの分類の仕方に、正常系テスト異常系テストという分類の仕方があります。 正常系テストは正しい入力に対するソフトウエアの動きを確認するテストで、異常系テストは正しくない入力に対するソフトウエの動きを確認するテストです。組み込み系のソフトのテストではこれに加えて準正常系を確認するテストも重要です。

正常系テストは割と判り易いので、テスト設計でもそんなに戸惑う事はありません。ところが異常系テストというのは、実際にテスト設計をしてみるとすぐに困った事が起こります。どれだけの種類の正しくない入力を洗い出して異常系のテストの項目を洗い出したら良いのか、テスト設計のゴールが見えなくなる、という事がよく起きてしまいます。

これは、正しくない入力としてどんな内容を想定したら良いのか、が明確に決まっていない場合によく起こります。そんな時には、異常系を準正常系と(真の)異常系に分けてテストの設計をすると判り易くなります。

この記事では、準正常系とはどんなものなのかについて、(真の)異常系との違いに焦点を当てる事で、できるだけ判り易く紹介しまします。なお準正常系の具体的な例は、通信プロトコル状態遷移ハードウエア制御 に分けて別の記事でも紹介していますので、そちらも一緒にご覧ください。

正常系のテストは仕様に沿って簡単に設計できます

正常系のテストとは、ソフトに正しい入力が与えられた時に、そのソフトが持つ機能が正しく動作している事を確認するためのテストです。少し言い方を変えると、そのソフトが持っている機能がちゃんと動作してい事を確認するための機能テストとも言えます。

例えば、A=B+10 という1行の計算式で作られたソフトウエアのテストを例にして考えてみましょう。ソフトウエアの仕様として B は1から3までの整数という制限があるとしましょう。正常系テストとしては、入力の B に 1, 2, 3 の3つの値を入れた時に、出力の A が 11, 12, 13 となる事を確認すれば良いですね。これでこの計算式の機能が正しく動作している事が確認できたので、正常系のテスト設計は終わりです。

異常系はいろいろな異常入力を考えるとテストケースがどんどん増加

では、異常系のテスト設計をしてみましょう。正しくない入力として何を想定すれば良いでしょうか? 例えば境界値分析の手法を使って正しくない入力の値を設計するなら、Bの値の境界値のうち正しくない値となる 0 と 4 を入れれば良いですね。では、これだけで異常系のテストの項目として十分でしょうか

残念ながら実際にソフトウエアが使われる場面では入力Bにいろいろな値が入力される可能性があります。人が入力する場合もあれば通信で他のコンピュータから値が伝わる事もありますが、人は間違いをする事もありますし通信ならどこかで通信エラーが発生して値の一部が変わってしまうかもしれません。その様な事を想定すると正しくない入力の値としては、色々な物が想定されます。例えば 100 とか -300 とか 999999999999999999 というような正しくない整数値が入れられる事もありますね。或いは 0.001 とか 10.34 とかの実数が入力される事もあれば、"heihei-ho" と 半角の英数字が入力されたり、”唯我独尊” と漢字が入力されたり Tab のようなコントロール文字が入力されたりと、正しくない入力の値はバリエーションを考えだすと色々とでてきます。

正しい入力はソフトの仕様に定義されているので簡単に洗い出せるのですが、正しくない入力は装置やソフトの作りによっていろいろな入力が考えられるので、いざ洗い出し始めると、どんどん異常な入力値の種類がでてきてしまいます。それでは異常系のテストでは、どこまでの正しくない入力値を想定してテスト設計をすれば良いのでしょうか? どこか適当な所で正しくない入力値の洗い出しを打ち切らないと異常系のテスト設計が終われませんね。

ソフトに作り込まれている異常値の処理は準正常系

そんな時には、異常系をさらに準正常系(真の)異常系に分けて考えると、正しくない入力の洗い出しに1つの方針ができて、異常系のテスト設計を妥当な範囲で終わらせる事ができます。では、準正常系と(真の)異常系とは何なのでしょうか?

簡単に言うと、準正常系のテストとはソフトウエアの設計者が想定した不正な値が入力された時の動作を確認するテストで、(真の)異常系のテストとはソフトウエアの設計者が想定しなかった/出来なかった不正な値が入力された時の動作を確認するテストです。ソフトウエアの設計者が想定した不正な値というのは、とても分かり易くて明確になっています。なぜなら、それらの値に対する処理がプログラムのソースコードとして実装されているからです。

少し具体的にC言語の switch case 文で疑似コードを書いてみるとこんな感じですね。

 switch ( B の値)  {

       case  Bの値が整数で 1から3の間:A=B+10 を実行する

  case Bの値が整数で 0以下か 4以上:入力範囲は1から3ですとエラーを返す

  case Bの値が実数:入力値は整数ですとエラーを返す

  default: 入力値異常とエラーログを記録して何もせずに終了する

  }

1つ目の case の箇所には正常系の処理が書いてあり、2つ目と3つ目の case の箇所にはこのソフトウエアの設計者が想定した正しくない入力の値とその入力値に対する処理が書かれています。この2つ目と3つ目の case の箇所に書かれている条件が、このプログラムコードでの準正常系です。

そしてこの設計者がコードに作りこんでいる準正常系のプログラムコード、つまり正しくない入力の値に対する処理が、設計者の考えた通りに動作している事を確認するのが準正常系のテストになります。ですのでこの場合の準正常系のテストとしては、異常な入力の値として、-1 と 4  に加えて、2.15 という実数を入力すれば、網羅できます。

ソフトに作りこまれていない異常値の処理が(真の)異常系

そして、このソフトウエア設計者はそれ以外の想定外の値が入力された時には、 default の箇所の処理を実行する事で、この処理が引き続き動作し続けるようコードを作成しています。そしてdefault の箇所に書かれている条件が、このプログラムコードでの(真の)異常系です。 正常系と準正常系で入力した「以外」の異常な値を何か1種類入力すれば、この(真の)異常系の動作を確認できます。 この例でいれば文字列や制御コードを入力すれば、default の箇所の処理が確認できすので、これが(真の)異常系のテストになります。

これを纏めると、テスト設計として以下のような条件の入力値を考えれば良いという事になりますね。

  • 正常系テスト:入力値は整数で1から3の値
  • 準正常系テスト:入力値は整数で0以下か4以上、または実数の値
  • (真の)異常系テスト:整数、実数以外の何かの値(文字列や制御コード)

準正常系テストの考えは通信プロトコルやハードウエ制御にも使える

このような単純なソースコードの場合以外にも、準正常系と(真の)異常系という考え方はテストの設計をする上で割と使いやすい考え方です。例えば通信プロトコルであれば、普通は何等かのエラー検出機能が定義されています。それらのエラー検出機能で通信エラーが見つかった時の処理もプロトコルの仕様として明確に定義されています。これらのエラー処理が正しく実行される事を確認するのは準正常系のテストです。

一方でプロトコルのエラー検出機能に定義されていないようなデータ通信の異常が起きた時でも、プログラムはハングアップせずに動作を続ける必要があります。そのような状態のテストが(真の)異常系のテストになります。

同じような考え方で、ハードウエアを制御する機能のテスト設計でも、準正常系と(真の)異常系という考え方は使いやすいです。ハードウエアが返してくるステータスとして定義されているエラーコードに対応する処理がちゃんと動作している事を確認するのが準正常系のテストで、定義されていないエーコードがかえってきた時の動作を確認するのが、(真の)異常系のテストっです。

準正常系と異常系には同値分割プラスα

このように準正常系と(真の)異常系とい分類の仕方を考えると、異常系テストのテスト設計で正しくない入力としてどこまでを洗い出せばよいかの方針が判り易くなります。あとは各々の方針に従って何種類の正しくない入力の値をテストデータとして準備するかの判断です。

ここはテストに掛ける事ができるコストや期間と、要求される品質のレベルによって色々と変わるのですが、原則としては以下のような考え方で良いと思います。

  • 正常系:正常な範囲について、代表値を1つと境界値分析で境界値を洗い出す
  • 準正常系:各々の方針について同値分割の考え方で代表値を1つ洗い出す
  • (真の)異常系:同値分割の考え方で代表値を1つ洗い出す

これだと、準正常系や(真の)異常系についても、テストケースの洗い出しが再現無く増えていく事は避けられて、割と実現可能で妥当な件数のテストデータを洗い出す事ができます。もちろん、求められる品質が高い場合や、十分なコストやテスト期間が取れる場合には、準正常系や(真の)異常系のテストデータとして、代表値以外にもいろいろな事を想定した値を考えると良いですね。

異常系と準正常系についてはテストの分類の記事にも書いてあります

正常系テスト、準正常系テスト、異常系テストについては、以下記事でもう少し具体的に紹介していますので、興味のある方はそちらもご覧ください。

テスト名・正常系と異常系と準正常系
テスト名・通信プロトコル処理での準正常系テスト
テスト名・状態遷移での準正常系テスト
テスト名・ハードウエア制御での準正常系テスト
 その他のお話に戻る