test
テスト
testing

テスト技法について古典から改めて学んでみる

More than 3 years have passed since last update.


テスト技法について古典から改めて学んでみる

普段なにげなくしている「テスト」

しっかりと学んでいる機会がなかったので、「ソフトウェアテスト」の古典として

長く使われている基本的な技法やテストの哲学について語られているJ・マイヤーズの名著、

『ソフトウェア・テストの技法 第2版』を読みました。

本著は米国で1979年に出版され、その翌年には日本で翻訳版が出版されました。

その後本日まで長い間語り継がれてきました。

JUnitなどのツールを紹介した本、その時のテスト技法について紹介する本は

雨後の筍のようにあります。ですが、

「そもそもテストとはなにか」

「テストをする際のエンジニアとして抑えておくべき姿勢・哲学はなにか」

という根本的な問に対して答えを出している書籍だからこそ、

時勢に流されずに長い間読まれてきた書籍なのかなと思いました。

Amazonのレビューを読んでいただいても、確かに翻訳に少し違和感があると言われれば有ります。

でも、QAさんのようにテストを本職としている人はもちろん、エンジニアとしていろいろなテスト技法を学ぶ前に一度は目に通しておくべき一冊ではないかと思いました。本著で特に気になったところを紹介します。


テストの心理学


  • テストとは、 エラーをみつけるつもりでプログラムを実行する過程 である

  • テストとは、 破壊的な過程であり、サディスティックな過程でさえ ある

  • 良いテストケースとは、まだ発見されていないエラーを検出する確立の高いもの である

  • 成功したテストケースとは、まだ発見されていないエラーを検出したもの である

  • テストケースにおける不成功とは、エラーが見つかったことではなく、エラーが見つからなかったこと である


ソフトウェアテストの原則

原則番号
原則

1
テストケースの必須条件は、予想される出力または結果を定義しておくことである

2
プログラマは自分自身のプログラムをテストしてはならない

3
プログラム開発グループは、自分たちのプログラムをテストしてはいけない

4
それぞれのテストの結果を完全に検査せよ

5
テストケースは、予想できる正しい入力条件ばかりでなく、予想しないあやまった場合も考えて書かなければならない

6
プログラムを調べるのは、それが意図されたように動くかどうかをみただけでは、なかば成功したにすぎない。残りの半分は、意図されなかった動きをするかどうかを調べることである。

7
プログラムが本当に使い捨てのものでないかぎり、そのテストケースも使い捨てにしてはならない

8
エラーは見つからないだろうと言う仮定のもとにテストの計画を立ててはいけない

9
プログラムのある部分でエラーがまだ存在している確立は、すでにその部分でみつかったエラーの数に比例する

10
テストとは、非常に創造的であり知的に挑戦しがいのある仕事である


検査のためのエラーチェックリスト


この節でのチェックリストは、ソフトウェア・エラーを長年にわたって研究してきた

筆者がまとめたものである。チェックリストは、プログラミング言語にはまったく関係がなく、

エラーの殆どは、どんなプログラミング言語にでもおこりうる。



データ参照エラー


  1. 値がセットされていない変数を使っていないか

  2. 添字の値が限界値内にあるか

  3. 整数でない添字を使っていないか

  4. 懸垂参照(ポインタや参照変数を使っての参照で、現在参照された記憶域が割り当てられているか)はないか

  5. ある記憶域が、属性の異なる別名をもつ場合、この記憶域でのデータ値は、これらの名前のどれか1つで呼ばれた時に正しい属性を持つか

  6. 変数の持つ値は、コンパイラで判断されている以外の型や属性をもっていないか

  7. 内部あるいは外部番地付の問題があるかどうか

  8. 参照された記憶域はコンパイラが期待している属性をもっているのか

  9. あるデータ構造が複数の手続き関数かサブルーチンで参照されている場合、その構造はそれぞれの手続関数に対して同一の形に定義されているか

  10. 文字列の添字付けのとき、文字列の限界を超えていないか

  11. オブジェクト指向言語で、すべての継承が正しいか


計算エラー


  1. 矛盾したデータ形式(文字列とか)をもつ変数を使って計算してはいないか

  2. 異なるモードの変数を混ぜて計算してはいないか

  3. 違う長さの変数の計算はないか

  4. 代入文のセットされる側の変数のデータ型が、右側の式のデータ型や結果より小さくはないか

  5. 式の計算中に、オーバフローやアンダフローの例外の可能性はないか

  6. ゼロで割っていないか

  7. 2進数表現の不正確性はないか

  8. 意味のある限界を超えた変数への値セットはないか

  9. 演算子の順序は正しいか

  10. 整数計算のあやまった使い方をしていないか


データ宣言・データ定義エラー


  1. すべての変数が明白に定義されているか

  2. デフォルトの属性を持っているか

  3. 初期値セットが正しい値をセットしているか

  4. 正しい長さ・データ型が与えられているか

  5. 変数の初期値セットはその記憶域の型と一致しているか

  6. よく似た同じような名前を持つ変数はないか


比較エラー


  1. 矛盾するデータ形式同士の比較はないか

  2. 混じったモードの比較はないか

  3. 比較命令は正しく使われているか

  4. ブール代数式は意図したとおりに表現されているか

  5. 比較とブール代数の命令が混在していないか

  6. 10進数の2進数近似や誤差切り捨てのためのエラーの原因になるような2進数表示の分数と浮動小数点の数の比較はないか

  7. 命令の解釈と実行の順序は期待通りか

  8. ブール代数式のコンパイラによる解釈方法を理解しているか


制御流れエラー


  1. 複数方向への分岐数が限度を超えていないか

  2. ループは停止するか

  3. プログラムは停止するか

  4. 入り口条件のためどこかのループがとばされていないか

  5. ループでの可能な中断が正しくおこなわれているか

  6. ループの反復回数は意図したとおりか

  7. DO/END命令が合っているか

  8. すえての場合を網羅していない判定はないか


インタフェイスエラー


  1. 入力パラメータの数が引数の数と正しいか

  2. パラメータと引数の属性が一致しているか

  3. パラメータと引数の単位系が一致しているか

  4. 引数の数がパラメータの数と等しいか

  5. よばれたモジュールへ送られる引数の属性はパラメータの属性と等しいか

  6. 呼ばれたモジュールへ送られる引数の単位系はパラメータの単位系と等しいか

  7. 組み込み関数への引数の数・属性・順序は正しいか

  8. 現在使われている入口店と関係のないパラメータへ参照しているものがあるのではないか

  9. 入力だけの引数が変更されていないか

  10. 大域変数定義がモジュール間で一致しているか

  11. 引数として定数が渡されているのか


入力/出力エラー


  1. ファイル属性が正しいか

  2. OPEN命令は正しいか

  3. 形式指定がI/O命令と一致しているか

  4. バッファの大きさはレコードの大きさに合っているか

  5. 使用前にファイルはOPENされているか

  6. ファイルのおわりの条件が正しく処理されているか

  7. I/Oエラーは正しく扱われているか

  8. 出力情報に何かつづりのエラーはあるか


他のチェック


  1. 相互参照索引表上に参照されていない変数があるか

  2. 期待していた属性リストであるか

  3. 警告または通告メッセージがあるか

  4. 入力の妥当性がチェックされているか

  5. 欠けている機能はないか


モジュールテスト(単体テスト)


モジュールテストをする3つの動機


  1. モジュールテストとは、最初にプログラムの小さなユニットに着目するため、テストの組み合わせの要素を管理できる

  2. エラーが見つかった時に、特定のモジュールの中にあることがわかるので、デバッグが容易

  3. 複数のモジュールを同時にテストする機会を与えてくれるため、テスト過程を並行して行うことができる


トップダウンテストとボトムアップテストの比較

トップダウンテスト

長所

1. 主な流れがプログラムの頂上の方へ向かっているならば、すぐれている

2. I/O機能が追加されれば、テストケースの表現が容易

3. 早期の骨組みプログラムはデモが容易で、モチベーションが上がる

ボトムアップテスト

長所

1. 主な流れがプログラムの底辺の方へ向かっているならば、すぐれている

2. テスト条件が作成しやすい

3. テスト結果がみやすい


上級テスト


仕様書の目的


  • 要求仕様書はプログラムが必要な「理由」を示し

  • 目的仕様書はプログラムが「何をどのように」なすべきかを示し

  • 外部仕様書はユーザに対してプログラムの正確な表現を示し

  • そのあとの過程で作成する文書(システム設計 > プログラム構造設計 > モジュール・インタフェイス使用 > コード)は、詳細化のレベルが深まるにつれて、そのプログラムがどのようにして組み立てるかをしめs


テストケースの15の範疇について


機能部分テスト(facility testing)

目的仕様書に書かれている機能を満たしているかどうかのテスト。


大容量テスト(volume testing)

プログラムに大量のデータをあつかわせることによるテスト。


ストレステスト(stress testing)

プログラムに重い負荷または力を掛けることによるテスト。


有用度テスト(usability testing)

ユーザインターフェースなどをふくめた、有用度のテスト。


秘密保護テスト(security testing)

プログラムが秘密保護に対する耐性をもっているかどうかを確認するためのテスト。


効率テスト(performance testing)

実働負荷と構成条件のもとで許容される応答時間や処理出力を持っているかどうかのテスト。


記憶域テスト(storage testing)

仕様を満たす記憶域が実装されているかどうかのテスト。


構成テスト(configuration testing)

OS・DBといったいろいろな種類のハードウェア構成をサポートしているかどうかのテスト。


互換性/構成/変換テスト(compatibility/configuration/conversion testing)

バージョンごとの互換性や変換手順のテスト。


設置テスト(installability testing)

導入手順のテスト。


信頼性テスト(reliability testing)

稼働要求に対する信頼性のテスト。


回復テスト(recovery testing)

回復機能が正しく働くかどうかのテスト。


サービス性テスト(serviceability testing)

保守能力の性質に関するテスト。


文書テスト(documentation testing)

文書の正確さのテスト。


手続きテスト(procedure testing)

人手による手続きを含んだシステムテスト。


テスト計画と制御

良いテスト計画に必要な内容。


  1. 目的

  2. 終了基準

  3. スケジュール

  4. 責任

  5. テストケース・ライブラリと標準

  6. ツール

  7. コンピュータ時間(コンパイルなどに必要な時間、今は不要?)

  8. ハードウェア構成

  9. 統合計画

  10. 追跡手続き

  11. デバッグ手続き

  12. 復帰テスト

あと、プロジェクトでは

スケジュールが大幅に遅延した時の「アクションプラン」も立てておくように、

とアドバイスを貰いました。


デバッグ


エラー位置発見の原則

精神論。


  • 考えよ

  • いきづまったときは、明日までのばそう

  • デバッグ道具は2番めの手段として使おう

  • 実験を避けよう、実験は最後の手段である


エラー修正の原則

経験論。


  • ひとつのバグがあるところには、別のエラーもある可能性が高い

  • エラーの兆候ではなく、エラーそのものをなおそう

  • 修正が正しいという確立は100%ではない

  • 修正が正しい確立は、プログラムが大きいほど落ちる

  • エラー修正は、新しいエラーを生む可能性があることに注意しよう

  • エラー修正の時、しばらく設計段階にもどってみよう

  • オブジェクト・コードではなくソース・コードを変更しよう


おまけ

今回のプロジェクトでテストの設計とか各ドキュメントの責任者を努めさせてもらえることになりました。

というか、前回のプロジェクトで理解が半端なままだったので、どうしてもテストをしっかり

学んでおきたかった。

とはいえ実際設計をはじめて見ると、わからないことばかり。

もちろん、ドキュメントは作れるし、なんとなくの全体設計やスケジュールを立ててみたけれど、

本当にこれでいいのか?という疑問がなかなか拭えずにいました。

そんな時、

・社内のスーパーQAさんにアドバイスをもらった

・その後本著でも考え方的なところを補強した

というやり方でなんとか納得の行く設計ができたと思っています。

テストは奥が深いです。