「知識ゼロから学ぶソフトウェアテスト」を読了しました。
感想とまとめについて書いていきます。
感想
前回,「プログラマが知るべき 97 のこと」という書籍を読んだときに,テストの重要性について何度も書いていました. そのため,テストについて詳しく学びたくて,入門書である本書籍を読むきっかけになりました。
著者の高橋寿一さんは,複数の企業でテストに従事した経験がある方です. フロリダ工科大学大学院で修士号を取得,広島市立大学にて博士号を取得,といったテストへの学術的な知識も持っている方で。
タイトルの「知識ゼロから学ぶ」からわかるように,知識がない人でも理解できるように口語的かつ抽象的な記述されているのが特徴です.
私は基本情報技術者試験の勉強をしているときに,「ホワイトボックステスト」,「ブラックボックステスト」,などの単語を学びましたが,単語の意味だけでなく本質的な意味をこの本で学ぶことができました.
この本の良い点は以下だと考えます.
- 初学者にも理解できるような表現.
- 著者の体験談に基づく記述
- 浅く広くソフトウェアテストをカバー
そのため,悪い点は良い点の裏返しだと考えます.
- 結論から先に記述しないので,わかりづらい文章や意味がわかりにくい例などがある.
- 体系的に学べない
- 口語が多い
- 浅く広くカバーすることが目的なので実践書ではない.
これらの悪い点のいくつかは著者が文章中になんどか言及しているのでそれは納得してよむべきです. そのため,「結論から先に記述しない」,「口語が多い」ような書籍に苦手意識をもつ人には絶対に購入しないことをおすすめします.
この本は,「ソフトウェアテスト」に対して知識が皆無の人が読むべきであって,ある程度わかっている人,実践的なことを知りたい人,そして,この本を一通り読んだ人は他の本を読むべきだと思いました.
まとめ
「印象に残ったこと」,「今後も実践していきたいこと」などを記述していきます.
ソフトウェアテストは最もポピュラーな品質改善方法である
- Steve McConnell,コードコンプリートの編集長
テスト担当者の心得
- バグを全部見つけるのは無理だと心得ろ!
- エラーは見つからないだろうという仮定のもとにテストの計画を立ててはいけない
- プログラムのある部分でエラーがまだ存在している確率は,すでにその部分で見つかったエラーの数に比例する.
- ソフトウェアテストで重要なのは,どの部分にバグが出やすいのか,そこにどのようなテスト手法を適用すれば十分な品質が得られるか知ることである
ホワイトボックステストとは
- プログラムの論理構造が正しいかを解析するテスト
- ホワイトボックステストの論理構造の正しさのみテストするため,ソフトウェアの使用が間違っていることから起こるバグは発見できない
制御パステスト法
- プログラムがどのような振る舞いをして,どのように制御され実行されていくかをテストする.
- カバレッジの値をとるために使われるので,制御パステストからは逃げられない.
- 制御パステストはエンジニアに自信を与えるテスト手法
ステートメントカバレッジ
- コード内の命令文(ステートメント)を少なくとも 1 回実行する.
- 役に立たないとまではいはないが,非常に弱いテスト手法.
ブランチカバレッジ
- 分岐コードに対してそれぞれの判定条件が TRUE,FALSE の結果を少なくとも 1 回ずつ持つようにテストコードを書くこと.
- ブランチカバレッジを全体に対して適用することは大変だが,全体に対してじゃなくても適用することで効果を得られることがわかっている.
カバレッジ基準
- 一般の商用ソフトウェアなら 60~90%程度で十分(筆者)
- カバレッジを測定せずにソフトウェアを出荷するのはリスクの高い行為
- カバレッジを測り,さらに時間的な余裕があれば,なぜテストケースが 70%カバーできて,残りの 30%はできないかを検討する価値は十二分にある.
カバレッジテストでカバーされないコード
- エラー処理.ほとんど起こり得ないようなエラーの処理など
- 使われていないコード.
カバレッジテストで検出できないバグ
- プログラムのループに関するバグ
- 要求仕様自体が間違っていたり,機能が備わっていないバグ
- データに関するバグ
- タイミングに関するバグ
カバレッジテストの罠
ホワイトボックステストの復権
- 2010 年を杉田あたりから,アジャイルの XP やスクラムが開発スタイルとして流行り出すと,またホワイトボックステストが脚光を浴びるようになった.
- アジャイル手法ではホワイトボックス手法を用いたユニットテストが MUST だから.
Test Driven Development(TDD)
- アジャイルとは,簡単にいうと「短いサイクルでコーディング・テストをまわして,変更があっても対応できるようにする」こと
- XP にはテスト・リファクタリング・継続した結合,という要素が明確に記述されている.
- TDD の基本は
- 小さく動作しないテストを書く(コンパイルは通らなくていい)
- テストを通すコードを書く
- 重複したコードの削除
- TDD によって「ユニットテストをやっている暇はありません」という輩がでなくなる.
- 「Kent Beck が推進する TDD をやりましょう」リファクタリングは,「まずテストが通るコードをどんな汚い形でも最小限の時間で実装できるものを書く」そして,「それをきれいにまっとうな形に成整する」ということ.
- TDD の本質は確実に品質保証するというより,スピードを持って開発し,そして変更に対して耐性を持つこと.
ソフトウェアというものは 4 つの仕事しかしない.なので君らはその四つの振る舞いをテストすれば良いのだ.
以下の 4 つの振る舞いさえテストすれば完璧
- 入力を処理する
- 出力を処理する
- 計算をおこなう
- データを保存する
ブラックテストの基本
- 同値分割法と境界分割法
同値分割法とは
- 入力領域を「同値クラス」という部分集合に分割し,その部分集合に入る入力値を等価とみなす作業のこと.
有効同値と無効同値
- 有効同値:プログラムが期待する入力値
- 無効同値:それ以外のあらゆる値
- 有効同値に対して,無効同値は多くなりやすいので省略することが多い.
- そのとき,「テストケースで省略するのはやむを得ないが,その省略されたテストケースでバグを出してはいけない」
- 省略しても無効同値がカバーできていない範囲が無いようにする.
境界値分析法とは
- 境界:「無効同値と有効同値との間の値」,もしくは「有効同値と有効同値の間の値」
- プログラムで「境界」と呼ばれる場所は常にバグが潜んでいるので,境界値近くは詳しくテストをする必要がある.
- なぜなら,プログラム上は無効同値と有効同値の間に必ず条件文が必要になり,その文が正しくかけていないことがあり得るため.
On-Off ポイント法(境界をテストする)
- On-Off ポイント法:境界のどの値をテストするかを考えるのに用いる
- 異なる処理が行われる一番近い二点をテストする.
経験則によるテストケース
- 十分なスキルがなかったり,時間がない場合に,「データを入力する機能がある場合,必ず『良いデータ』と『悪いデータ』を入力しなさい」
- 良いデータ
- ユーザーがよく使いやすそうなデータ
- プログラムが許す最小のデータ
- プログラムが許す最大のデータ
- ゼロ(もしくは悪いデータとして)
- 悪いデータ
- 非常に小さなデータ
- 非常に大きなデータ
- 長いデータ
- 無効なデータ
ディシジョンテーブル
- すべての入力の組み合わせを表にし,その入力に対する動作もしくは出力を明記する.
- 表には,状態,ルール(状態の組み合わせ),動作(アクション)がまとめられ,その表の通りテストを実行する.
- これによってすべての入力パターン(状態)がテストされ,その入力パターンが期待通りの動作をしているかが「動作」によって確認される.
- 表を使ったテストは非常に小さいソフトウェアか,あるいは大きなソフトウェアの一部分をテストするときにしか使えない.
状態遷移遷移テスト
- 「状態」をモデル化してテストを行う手法.
- 状態遷移は大きく分けて状態(state)と遷移(transition)の 2 つによって表現される.
- 状態(state)とイベント(event)の組み合わせにより,アプリケーションがどのような状態になるかを表で示す.
状態遷移テストでは以下のようなバグが発見される
- 期待していない状態に遷移するバグ
- 遷移自体がない場合
- 期待していない状態に遷移するバグ
- 遷移自体がない場合
状態遷移テストが適しているソフトウェア
ランダムテスト
- アドホックテスト,アドリブテスト,ランダムテスト,モンキーテストなどと呼ばれる.
- 結構な数のバグを見つかってしまうところが問題.
- 全体の数10%のバグは見つかる
ブラックボックステストのまとめ
- 境界値テストをやる.境界値に関わるバグをすべてつぶす.
- 入力エリアが 2 つ以上あるようなダイアログとかあるようならディジジョンテーブルテストをおこなう.
- 状態があるなる,状態遷移をやる.
- この手順をおこない,「ブラックボックステストのアプローチが間違っている」か「ホワイトボックステストでしか見つからないバグだった」かどうかを判断する.
- 60%のバグを見つけ,そのほかのバグがなぜ発生したか,そしてどうやって防止するかに時間を費やす.
探索テストとはソフトウェアの理解とテスト設計とソフト実行を同時に行うテスト(Cam Kaner)
- 探索的テストとは
- ソフトウェアテストの 1 つのスタイル
- 個人に自由意識を持たせるとともに責任をより明確にする
- 一個人のテスト活動である
- 継続的にテスト活動を洗練させる
- 探索テストは以下の活動を行う
- テスト関連の学習
- テスト設計
- テスト実行
- テスト結果を報告
- 成熟したテスト活動
- 上記の活動をプロジェクト期間中並行して行う
探索的テストはテストケースベースのテストより効率の点で優れている
- テストケースベースの大きな落とし穴を埋めようとするのが探索的テスト
テストケースベースの問題点と探索的テスト
- テスト設計,ケース作成を,早い段階で行う
- テストケースドキュメント作成には時間がかかるので,実際にテストする方が早い
- テストリリースが出てきて,その早い段階で作ったケースを実行する
- 触ってみていろいろテストすることでいろいろ問題が判る
- 同じテストケースでたくさん実行する
- スキルのあるテスト担当者がテストするからたくさん回帰テストのバグが見つかる
- 「テストケースをいちいち事前に書くよりも,ソフトウェアをテストしながら考えて実行する」
「テスト設計・ケース設計を早い段階で行う」デメリット
- ソフトウェアプロジェクトは要求仕様はいい加減で,境界値がどこにあるかなんてちゃんと書かずに,その結果としてテストケースもちゃんと書かずにテスト実行フェーズに突入してしまう.
- 早すぎるテストケース作成は著しいソフトウェアテストの工数増大をもたらす.
「同じテストケースをたくさん実行する」デメリット
- 何度も繰り返すは,あまり意味がない,必要なのは
- テストを実行しながら,どこか他の部分に問題がないかを考え,そこをテストすること
- ソフトウェアで弱いところ見つけたら,そこに重点を置き,その部分を十分にテストする
探索的テストのサンプル
- クライテリアを決める
- 探索的タスクを実行する
クライテリアを決める
ソフトウェアであるべきかのクライテリアを決める
探索的テストのタスク実行
- ターゲットソフトウェアを決める
- 機能をリストアップする
- 弱いエリアを見つける
- 各機能のテスト及びバグの記録:3でテストを実行し,問題があればバグの報告を作成する.テストケースは書かない.テストを行ううえでテストケースを書くことに時間がかかり,テストの実行自体の時間が削られてしまうことを避けなければならない
- 継続的なテストの実行:「テスト担当者が複数いるのなら,担当範囲を交換して同じ結果がでるか確認する」,「ソフトウェアの環境を変える」,「バグ修正により他の機能に悪い影響が出ていないかを確認する」,「重要機能に対してシンプルなテストをおこない,ソフトウェア全体の品質レベルが下がっていないかを確認する」
探索的テストのまとめ
- 探索的テストをしない理由はない
- 探索的テスト+スキルのあるテスト担当者では,すごく短い時間で良い結果になる
非機能要求
- 重要な特性
- 機密性
- 信頼性
- パフォーマンス
非機能要求の難しさ
- 非機能要求テストはそれぞれの非機能要求に対してテストのアプローチが異なる
パフォーマンステストの3つの注意点
- パフォーマンスの定義は明確に
- 要求定義通りのテストケースを書かない
- パフォーマンステストは後回しにしない
パフォーマンステストの 5 つのステップ
Step1:アーキテクチャバリデーション
Step2:パフォーマンスベンチマーク
Step3:パフォーマンス回帰テスト
Step4:パフォーマンスチューニング,アクセプタンステスト
Step5:24×7 パフォーマンスモニター
セキュリティの3つの要素
- 機密性:アクセスの認可された者だけが,特定の情報にアクセスできることを確実にすること
- 完全性:「情報及その処理方法が正確,かつ完全であること」を維持・保護すること
- 可用性:認可された利用者が必要なときに,特定の情報及関連する資産にアクセスすることを確実にすること
セキュリティテストの難しさは「悪意のある攻撃」に対しソフトウェア及びそのシステムが耐え得るかを確かめるテスト手法が存在しないところ
セキュリティテストの 2 つのパターン
- プログラム構造の不備を突き,そのプログラムの制御を奪ったり,不能にしたりする場合
- プログラムのデータの不備を突き,そのデータを改竄する.
信頼性
- 「指定された条件下で利用するとき,指定された達成水準を維持するソフトウェア製品の能力」
- 「信頼性を構成する要素には成熟性(maturity),障害許容性(faulttolerance),回復性(recoverability)
信頼性工学では「バグは有限」,ソフトウェアテスト技術において「バグは無限」
最悪のソフトウェアを出荷しないようにするには
- ちゃんと計画を立てスケージュールを守り,テストケースを的確に実行する.
テストプランの書き方
- IEEE829 のテストプランテンプレート,主な項目は以下
- テストプラン文書番号(Test plan identifie)
- レファンレンス
- はじめに(Introduction)
- テストアイテム(Test items)
- テストするソフトウェアのバージョン
- ソフトウェアがどのメディアでテストされているのか,それがどのハードウェアに依存しているのか
- テストすべき機能(Features to be tested)
- テストする必要のない機能(Features not to be tested)
- 以外と重要.既存のライブラリをテストするか否かでおおきく変わる
- アプローチ(Approach)
- 人員経過,トレーニングプラン(Staffing and training needs)
- 早く人員を投入し,早い段階からテストをすれば早くバグが見つかり,コスト削減に顕著に貢献する.
- スケジュール
- 承認
- 終了基準
遅れの出ているソフトウェア開発プロジェクトに人員を追加するとさらに遅れる(マーフィーの法則)
- 最後に頭数をたくさんつっこんで,バグをたくさん修正しても,良いことなんてない
明確に分離できる仕事の場合は増員により効率化できる
- スケジュールを正確に見積もることが最重要課題なのではなく,コントロールできるスケジュールが必要
テストマネージャが取り得る3つの選択肢
- ソフトウェアの品質を下げる
- 出荷を遅らせる
- 機能を削る
リスクとその対策
- リスク=問題の起こる確率 × 問題が起こった場合のダメージ
- 複雑度
- 新規性
- 変更
- 上位依存性
テストケースの書き方
- いつ,誰がやっても同じような結果が得られるように書かなければならない
テストケース管理ツールを使うメリット
- ツールを持ってテストケースを書くことによって,複数のテスト担当者が同じ粒度でテストケースを入力しやすい
- テストケースの管理がしやすい
テストケースはいくつ必要か
- 日付 テストを実行した日付
- テスト結果 テストが成功したのか失敗したのか
- 実施者 誰がテストを実行したか
- ビルド番号 どのビルドでテストを実行したか
- 環境 どんなコンピュータで実行したか,その際の OS の種類は,など
テスト開始のタイミング
テストは早く始めるほど良い ただ,要求仕様のバグは非常に優秀なテストエンジニアでないと発見できない
出荷基準(一例)
- 残存バグ件数が総件数の 0.5%以内
- テストケースの成功率 99%
長時間使用テスト(48 時間使用)でハングアップが一度もない
明らかにセキュリティ上の問題がある場合をのぞいて修正は思い留まるべき 最後の最後になってなんらかのコード修正を入れることは,それまで行ったテスト作業の努力を無にする危険がある.
品質を目に見えるものにするには
- 私情や恣意の入らないものを選ぶ
- 品質を十分代表するものを選ぶ
バグの数を管理するバグメトリックス
- 単純なバグの総数を管理する場合
- バグの総数ではなく重要度の高いバグの発見数を用いて,ソフトウェアの品質を見極める場合
- 単に数字だけを取り上げて判断するのではなく,その数字の性質をよく知ったうえで利用するべき
バグの修正にかかる時間(バグメトリックス)
- 一般的なプロジェクトでは,開発が進むにつれて開発者のバグ修正時間が増えていき,バグ一個あたりの修正時間が短くなっていく
- 出荷間際になってもバグの修正時間が短くならない場合は要注意.あらがな機能を追加しているか,バグの修正が非常に困難になっている
- 「修正困難なバグ」は「テストで見つけられにくいバグ」と等価
モジュールで見つかるバグ(バグメトリックス)
- モジュールもしくはコンポーネントごとのバグの数をみる.
- バグが多いモジュールを単純に品質が悪いとは言えない.なぜなら「テストチームが優秀」,「開発者が正直にバグを申告している」などが考えられるから.
- しかし,本当に品質が低い場合は危険.「一個のコンポーネントの品質が低ければ,ソフトウェア全体の品質は悪い」ということになる
ソースコードメトリックス
- コード行数(LOC:Line of Code)を測ることで,開発チームの健全性が見えることがある.
- コード行数が急に増えたり減ったりするような「特別な動き」があるときは何か負の要因が潜んでいる場合が多い.
- 原因を調査するべき判断材料になり得る.
コード行数とバグ密度
- バグ密度は以下の式で表される.「バグの数」は「無限」になることも理解して利用すれば,バグ密度は価値のあるメトリックスになる
- バグ密度 = (バグの数)/ KNCSS
Cyclomatic complexity(循環的複雑度)
- 循環的複雑度の値は以下のような意味がある
- 1~10:シンプルなプログラム.リスクは少ない
- 11~20:より複雑である.まあまあリスクが発生するかも
- 21~50:複雑,高いリスクを有する
- 51~:テスト不可能(著しく高いリスク)