『知識ゼロから学ぶソフトウェアテスト』


## はじめに
### ソフトウェアの品質が悪いとはなにか
* 品質が悪いとは: バグによって本来の機能が制限され、そのソフトウェアに期待される機能を顧客に提供できないこと

### テスト担当者の心得
* バグを全部見つけるのは無理だと心得ろ
* プログラムのある部分でエラーがまだ存在している確率は、すでにその部分で見つかったエラーの数に比例する
* ソフトウェアテストで重要なのは、どの部分にバグが出やすいか、そこにどのようなテスト手法を適用すれば十分な品質が得られるかを知ること

## ソフトウェアテストの基本 -ホワイトボックステスト-
### ホワイトボックステストとは
* ホワイトボックステストとは、プログラムの論理構造が正しいかを解析するテスト
* ホワイトボックステストは論理構造の正しさのみをテストするため、ソフトウェアの仕様が間違っていることから起こるバグは発見できない

### プログラムの振舞をテストする -制御パステスト法-
* 制御パステスト法は、プログラムがどのような振る舞いをして、どのように制御され実行されていくかをテストする
* カバレッジ率の値を取るために使われる
* 制御パステストによるコードカバレッジテストの本質は、フローチャートをちゃんとカバーすること

### ステートメントカバレッジ
* ステートメントカバレッジでは、コード内の命令文 (ステートメント) をすくなくとも一回は実行する
* プログラムによっては、ステートメントよりも分岐でのエラーが多いため、非常に弱いテスト手法 

### ブランチカバレッジ
* ブランチカバレッジは、分岐コードに対してそれぞれの判定条件がTRUE、FALSEの結果を少なくとも一回ずつもつようにテストケースを書く
* テストケースの数がかなり増えるのが問題
* バグがたくさん出ている部分に対してブランチカバレッジを実行したりする

### カバレッジ基準
* 一般の商用ソフトウェアなら60 ~ 90%程度で十分

### カバレッジテストで検出できないバグ
* プログラムのループに関するバグ
* 要求仕様自体が間違っていたり、機能が備わっていないバグ
* データに関するバグ
* タイミングに関するバグ

### カバレッジテストの罠
* 重要なのは自分たちで決めた妥当な目標を達成することであって、カバレッジデータに振り回されないように注意する
* カバレッジテストは非常にコストがかかるため、カバレッジテストをすると決めた時点で予算を組んでおく

## エンジニアがもっともよく使う手法 -ブラックボックステスト-
### ソフトウェアテストは簡単
* ソフトウェアは4つの仕事しかせず、その4つの振る舞いをテストすればよい
	1. 入力を処理する
	2. 出力を処理する
	3. 計算を行う
	4. データを保存する
* ブラックボックスとは、プログラムを一種のブラックボックスと見立てて、様々な入力を行うことによって、ソースコードを見ずにテストを行う手法

### どんな入力も正しく処理するためには -同値分割法-
* 同値分割とは、入力領域を「同値クラス」という部分集合に分割し、その部分集合に入る入力値を等値とみなす作業
* 問題は、無効同値の数が多くなること
* 無効同値のテストケースを省略するためのポイントは、すべてのエレメントを網羅している無効同値を選ぶこと

### バグの住む場所を探す -境界値分析法-
* プログラムで境界と呼ばれる場所には常にバグが潜んでいるので、境界値近くは詳しくテストする必要がある

##### 起こり得るバグのタイプ
以下の4つのバグタイプを頭に入れながらテストを書く。

1. >と>=の間違い
2. 数字の書き間違い
3. 境界がない (条件文書き忘れ)
4. 余分な境界

##### 境界をテストするために ~On-Offポイント法~
異なる処理が行われる一番近い二地点のテストをすること。

##### 経験則によるテストケース
データを入力する機能がある場合、必ず「良いデータ」と「悪いデータ」を入力する。

###### 良いデータ
* ユーザーがよく使いそうなデータ
* プログラムが許す最小のデータ
* プログラムが許す最大のデータ

###### 悪いデータ
* ゼロ
* 非常に小さなデータ
* 非常に大きなデータ
* 長いデータ (abcdefghijklmn.txt など)
* 無効なデータ

### 複雑な入出力のためのテスト -ディシジョンテーブル-
* ディシジョンテーブルは、すべての入出力の組み合わせを表にし、その入力に対する動作もしくは出力を明記する
* 表には、状態、ルール (状態の組み合わせ)、動作 (アクション) がまとめられ、その表の通りテストを実行する
* 問題は、ケース数が大きくなりすぎるため、非常に小さなソフトウェアか、あるいは大きなソフトウェアの一部分をテストするときにしか使うことができない

### GUIをテストする -状態遷移をテストする-
* 状態遷移テストとは、「状態」をモデル化してテストを行う手法
* 状態遷移は、状態 (state) と遷移 (transition) の2つによって表現される
* 期待していない状態に遷移するバグや、遷移自体ができないバグを発見できる
* 問題は、状態の数が増えると、テスト項目が増えすぎてテストができなくなる
* 状態遷移テストが適しているソフトウェア
	* GUIソフトウェア
	* オブジェクト指向ソフトウェア
	* 通信プロトコルテスト

### ブラックボックステストのまとめ
* まず境界値テストを行い、境界値に関わるバグをつぶす
* もし入力エリアが二つ以上あるようなら、ディシジョンテーブルテストを行う
* 状態が遷移するようなソフトウェアの場合は状態遷移テストを行う

### テストの方針
* テストはバグを見つける最適な手段だが完璧ではない
* 60%くらいのバグを見つけられれば御の字
* ということは、楽して60%のバグを見つけ、その他のバグがなぜ発生したか、そしてどうやって防止するかに時間を費やすことが、建設的なテスト担当者の役割

## 探索的テスト
### 探索的テストとは
* 探索的テストとは、ソフトウェアの理解とテスト設計とテスト実行を同時に行うテスト
* いちいちテストケースを書く代わりに、製品を学習した上でテスト設計して実行してバグ報告を並行して行えば手っ取り早い

### 効果的な探索的テストの方法

* テストを実行しながら、どこか他の部分に問題がないかを考え、そこをテストする
* ソフトウェアで弱いところを見つけたら、そこに重点を置き、その部分を十分にテストする
* 常に弱い部分を想像し、実行を繰り返しながらソフトウェア構造的に弱くバグの多い二割の部分を見つけ、そこから八割のバグを出しきること

### 探索的テストのサンプル
1. クライテリアを決める (表形式)
	* 横軸: Pass基準 / Fail基準
	* 縦軸: 機能性 / 安定性
2. 探索的タスクを実行する
	* 機能をリストアップする
	* 弱いエリアを見つける
	* 各機能のテスト及びバグの記録
	* 継続的なテストの実行

### 探索的テストのメリット・デメリット
* メリット: テストケースベースのテストより効率の点で優れている
* デメリット: 非機能要求のテストに向かない

## 非機能要求のテスト

* ソフトウェアには機能要求と非機能要求という二つの要求が存在する
* 非機能要求とは、品質特性のこと
* 重要な品質特性は、機密性、信頼性、パフォーマンス

### パフォーマンステスト
* パフォーマンスの定義は明確に
* 要求定義通りを逸脱するようなテストケースを作成する (テストはバグを見つけるためのものだから)
* パフォーマンステストは後回しにしない

### 信頼性
* 信頼性 = 指定された条件下で利用する時、指定された達成水準を維持するソフトウェア製品の能力
* ソフトウェアの信頼性を測るためには、信頼度成長曲線を書く必要がある
* 実際の顧客がもっとも使うと思われるオペレーションをした際のMTBF (平均故障間隔: Mean Time Between Failure) が使いやすい
	* MTBFの測定: 単位時間あたりどのくらいFailureに遭遇するか
	* １日の総テスト時間を測り、その中でどれだけハングしたかを数えたりする

## ソフトウェア運用の基本
### 最悪のソフトウェアを出荷しないようにするには
* 大事なのは、バグのない製品を出すこと
* そのためには、ちゃんと計画を立てスケジュールを守り、テストケースを的確に実行する、それだけ

### テストプランの書き方
* IEEE829を調整して使用する

### テストケースの書き方
* いつ、誰がやっても同じような結果が得られるように書くこと

## ソフトウェア品質管理の基本
### 品質を目に見えるものにするには
* テストという作業は、アウトプットが非常に見えにくい
* メトリックスデータを使用する場合、次の2点に気をつける
	* なるべく誤差がなく、人間の恣意に左右されないものを選ぶ
	* 開発するソフトウェアの品質を十分代表するものを選ぶ

### メトリックスの例
* バグの数
* 重要度の高いバグの発見数
* バグの修正にかかる時間
* モジュールで見つかるバグの数
* コード行数
* 複雑度

### Microsoftが使っているメトリックス
* バグのメトリックス
	* 時間軸でのバグの発見数
	* コンポーネントごとのバグの発見数 (バグが多すぎないか、もしくは少なすぎないか)
* テストのメトリックス
	* コードカバレッジ
	* テスト担当者以外のバグの発見数
	* テストケースの数と、テストの自動化率
* ソースコードのメトリックス
	* 追加、削除、変更されたコードの行数
	* KLOCs: どのくらいソースコードの行数が増加しているか
	* コードの複雑度: McCabeのルール
* ソフトウェアの信頼性メトリックス
	* 実際の顧客がもっとも使うと思われるオペレーションをした際のMTBF (Mean Time Between Failure)
	* 信頼性成長曲線
	* ストレステストを行った際のMTTF
* ビルドのメトリックス
	* ビルドにかかる時間
	* ビルドで見つかった問題
	* ビルドが失敗した原因
* スケジュールのメトリックス
	* 当初に立てたスケジュールと実際のズレ

## テストの自動化という悪魔
* テストの自動化を成功させる (コストを削減させる) ためには、自動化コードの保守コストを低く保つことが必要
* 自動化に向くテストと向かないテストをしっかり見極めた上で、自動化個どのメインテナンスにコストを最小限に抑えられるようにすることが、テスト自動化の鉄則
* 自動化に向くテスト
	* スモークテスト
	* パフォーマンステスト
	* APIのテスト
* 自動化に向かないテスト
	* 回帰テスト
	* グラフィックスやサウンドなどメディア関連のテスト

## それでもテストがうまく行かない人へ
### 組み合わせテストをやめる
* テスト担当者が忙しい原因は、テストケースの多さ
* その多さの要因は、組み合わせテストがテストケースの増大を起こしている
* 組み合わせテストで見つかるバグの数は、10%以下

##### おすすめのやり方
1. 入力ダイアログボックスがあれば、境界値テストを行い、単機能のデータ入力に対するバグを見つける
2. 複数の入力ダイアログボックスがあれば、ディシジョンテーブルテストを行う
3. ダイアログボックスの遷移があれば、状態遷移テストを行う
4. それでおしまい！

##### 組み合わせテストで見つかるバグ
1. グローバル変数を使っている
2. マルチプロセスやマルチスレッド間でデータを共有している

よって、組み合わせテストに関する問題はテストで見つけるのではなく、アーキテクチャを工夫して出ないようにすべし。

### 品質の低いモジュールを徹底的に叩く
* 基本的には品質の悪い一部のコンポーネントが全体の品質の足を引っ張る
* そのタコなもジュルを見つけて品質改善をすると、あっと驚くような品質のソフトウェアになる
* 80%のバグは20%のコンポーネントからきていて、全体のうち50%のコンポーネントにはバグが存在しない
* 20%のバグの発見は、モジュールごとのバグの発見数を調べれば、どこにバグがたくさんあるかはすぐわかる
* 巨大なソフトウェアですべてのバグを潰すことは不可能なので、致命的なバグを出さないことが重要だと考え、20%部分だけ潰していく

## 参考
http://www.amazon.co.jp/dp/4798130605