現場で役立つテストの基本

# 概要

新人エンジニアにとって、コーディングの学習については、入社時の集合研修等、それなりに機会があることでしょう。
一方でテスティングについては、「現場で覚えろ」という会社が多いのではないでしょうか？

本稿では、経験の浅い（概ね3年目以下の）エンジニアを対象に、現場だけでは得にくいソフトウェアテストの基本を解説します。

**Agenda**
1. テストの定義と関連性
2. テストマネジメント
3. テスト技法
4. テスト実施の心構え

# 1. テストの定義と関連性

ISO/IEC/IEEE 29119 はソフトウェアテストの国際標準規格です。
その中では、テストの定義と関連性を以下のような図で記載しています。

![スライド1.jpg](https://qiita-image-store.s3.amazonaws.com/0/122917/9cf582ab-2923-284b-e6ec-0f7ac5522d2a.jpeg)
出典：[ISO/IEC/IEEE 29119 Software testing - Part 1: Concepts and definitions](https://webdesk.jsa.or.jp/books/W11M0090/index/?bunsyo_id=ISO/IEC/IEEE%2029119-1:2013)
（日本語訳は執筆者）

## 1.1. 組織的テストプロセス

- 一貫性があり、効果的・効率的なテストを実施するためには、組織としてのテストポリシーとテスト戦略があることが望ましい
- 組織のテストポリシー
    - 目的、目標、組織内のテストの全体的な範囲について説明した、エグゼクティブレベルの文書
    - 組織的なテストプラクティスの確立やフレームワークを提供する
- 組織のテスト戦略
    - テストが組織内で行われる方法を定義した、詳細な技術資料
    - プロジェクト固有のものではなく一般的な文書
    - 組織内のいくつかのプロジェクトのためのガイドラインを提供 

引用：[60分でわかった気になるISO29119](https://www.slideshare.net/kjstylepp/60iso29119-wacate)（SlideShare）

## 1.2. プロジェクト内のテストプロセス

- 組織的テストプロセスを継承して計画
- プロジェクト内のテストプロセスは通常いくつかの「テストサブプロセス」によって実行される

## 1.3. テストサブプロセス

- テストサブプロセスは以下によって決定される
    - テストフェーズ（工程）
    - テストタイプ（種別）
        - テストタイプは1つ以上の品質特性と関連づけられる
    - テストサブプロセスには静的テスト（ソース構文チェック等）も含まれる

### 1.3.1. 品質特性

ソフトウェア品質の評価に関する国際規格としては、ISO/IEC 9126 があります。

- 機能性（functionality） - 機能とその特性に影響する特性群。機能には、必要性を明確に述べているものと、暗に示しているものがある。
- 信頼性（reliability） - ある状況がある時間続いたときにソフトウェアがどの程度機能するかに影響する特性群。
- 使用性（usability） - 利用するのにかかる手間、個人の努力などに影響する特性群。
- 効率性（efficiency） - ソフトウェアの性能やそれに要するリソース量に影響する特性群。
- 保守性（maintainability） - 何らかの変更を加えるのにかかる手間に影響する特性群。
- 移植性（portability） - 別の環境にソフトウェアを移行させる可能性に影響する特性群。

出典：[Wikipedia](https://ja.wikipedia.org/wiki/ISO/IEC_9126)

### 1.3.2. テストサブプロセスの具体例

※テスト技法については後述します。

|フェーズ|タイプ|技法|観点|品質特性|
|:--|:--|:--|:--|:--|
|単体テスト|機能テスト|ステートメントテスト|各関数について期待結果通り動作するか|機能性|
|結合テスト|機能テスト|状態遷移テスト|設計書に記載されている通り画面遷移するか|機能性|
|結合テスト|機能テスト|シナリオテスト|業務フローに沿ったテストシナリオを作成し動作確認|機能性|
|総合テスト|性能テスト|エラー推測|ピーク時を想定した環境を作り処理時間が性能要件内に収まるかを確認|効率性|
|総合テスト|セキュリティテスト|デシジョンテーブルテスト|全ての機能と職制の組み合わせでのアクセス制御を確認|機能性|
|受入テスト|ユーザビリティテスト|ランダムテスト|運用の妨げになる致命的な考慮漏れがないか|使用性|

ウォーターフォールモデルの場合、テストフェーズと、テスト設計のインプットとなるドキュメントあるいはテスト観点がV字型に対応する[Vモデル](https://ja.wikipedia.org/wiki/V%E3%83%A2%E3%83%87%E3%83%AB)という手法が広く知られています。

しかし、「テストタイプ○○は××フェーズでやるべき」「テストタイプ○○には××技法を使わなければならない」という決まりがあるわけではありません。

開発プロセスが何であれ、要は、テスト対象ソフトウェアに求められる品質特性を充足できるよう、テスト全体を戦略的に計画すれば良いのではないでしょうか。

# 2. テストマネジメント

## 2.1. テスト計画

- 前述した組織のテストプロセスに基づいて作成
- テストフェーズと、実施するテストタイプを定義
- 品質管理の計画値を策定
    - コード網羅率（カバレッジ）
    - KStepあたりのテスト項目数
    - KStepあたりの不具合摘出数　など
- テスト体制
- スケジュール
- テストの完了条件

### 2.1.1. コード網羅率（カバレッジ）基準

- 命令網羅(statement coverage)（C0）
- 分岐網羅(branch coverage)（C1）
- 条件網羅(condition coverage)（C2）
- 判定条件／条件網羅 (decision/condition coverage)
- 複合条件網羅 (multiple condition coverage)
- 経路網羅(path coverage)

出典：[Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%86%E3%82%B9%E3%83%88#.E5.91.BD.E4.BB.A4.E7.B6.B2.E7.BE.85.28statement_coverage.29.EF.BC.88C0.EF.BC.89)

## 2.2. テストモニタリング＆コントロール

- 計画と実際の進捗との比較、必要に応じた是正措置を行う
- モニタリング（計測）可能な状況を維持することが重要
- ステークホルダーへの説明も考慮すること

実務的に平たく言うと、テストの進捗管理と、課題・障害の管理、です。

課題・障害の管理については、以下のような点が重要であり、これらを管理できるように文書フォーマットや運用ルールを定めておくと良いでしょう。

- １件バグを発見したら、類似のバグが他の機能に潜んでいないかを調査すること
- バグを修正したら、その周辺機能への悪影響（デグレード）を及ぼしていないかを確認すること
- 埋め込み要因（コーディングミス、設計ミス、基本仕様の考慮漏れ等々）を切り分けておくこと

## 2.3. テストマネジメントの心構え

> **どのぐらいテストをすればよいかという質問に解はない**
>
> **「充分なテスト」とは「正しい状況判断を下すのに充分な情報を得られること」である**

未発見の重大なバグが残存していないことを、どのように判断するのか？
これは大変難しい命題です。
何らかの完了条件をテスト計画時に決めておくしかないわけですが、経験から学び、常に向上を心がけるしかないでしょう。

> **カバレッジも使い方による**
>
> **テストケースの項目数からは何も分からない**
>
> **テスト戦略はテスト項目より重要だと心得よ**

コードカバレッジや、KStepあたりのテスト項目数は、あくまで、進捗や品質の「一側面」しか測定できないと認識するべきです。
一つあれば充分な指標は存在しません。

引用：[ソフトウェアテスト293の鉄則](https://www.amazon.co.jp/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%86%E3%82%B9%E3%83%88293%E3%81%AE%E9%89%84%E5%89%87-Cem-Kaner/dp/482228154X)（書籍）

# 3. テスト技法

テスト技法については多岐に渡り、またその分類についても立場・人によって様々ですが、必ず**テストの五大要素**を含みます。

- **テストの実施者**：テストを実施するのは誰か
- **網羅性（カバレッジ）**：何をどこまでテストできるか
- **発見したい問題**：どんな問題を探すつもりでテストするのか
- **作業内容**：どのようなアプローチでテストするのか
- **結果の判定方法**：テスト結果の合否を判定する基準

出典：[ソフトウェアテスト293の鉄則](https://www.amazon.co.jp/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%86%E3%82%B9%E3%83%88293%E3%81%AE%E9%89%84%E5%89%87-Cem-Kaner/dp/482228154X)（書籍）

代表的なテスト技法について以下に解説します。

## 3.1. 同値分割

> 入力または出力を同じように扱えるグループに値を分けたものを同値クラスと呼び、それぞれの代表的な値を用いてテストを行う。 有効な同値クラスを有効同値クラス、無効（エラー）となる同値クラスを無効同値クラスと呼ぶ。

## 3.2. 限界値（境界値）分析

> 入力または出力を同じように扱えるグループに値を分け、その境界となる値を用いてテストを行う。プログラムのエラーは分岐の境界で発生する場合が多いため、限界値分析に基づいたテストを行うことで、同値分割に基づいたテストよりも多くの欠陥を発見することができる。

[同値分割と限界値分析の適用例](https://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%86%E3%82%B9%E3%83%88#.E5.90.8C.E5.80.A4.E5.88.86.E5.89.B2.E3.81.A8.E9.99.90.E7.95.8C.E5.80.A4.E5.88.86.E6.9E.90.E3.81.AE.E9.81.A9.E7.94.A8.E4.BE.8B)

引用；[Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%86%E3%82%B9%E3%83%88)

## 3.3. 組み合わせテスト

複数のパラメータの（メソッドの引数であったり、設定であったり）組み合わせをテストする場合、パラメータの全ての値と、パラメータ同士の全ての組み合わせをテストしようとすると、膨大な数になる場合があります。

例えば、100の値を取り得る3つのパラメータの組み合わせテストならば、100×100×100＝1,000,000通りのテストが必要になってしまいます。

そこで、以下のような手法で、現実的に実施可能な数までテストケースを削減します。

**1）ドメイン分割**
まず、同値分割／限界値分析を行い、各クラスの「代表値」を数個選択します。ドメイン分割とも言います。

**2）禁則条件の整理**
複数のパラメータの組み合わせをテストする際、禁則条件というものが存在する場合があります。
例えばOSとブラウザの組み合わせテストであれば、テスト対象ブラウザが動作しないOSとの組み合わせはテスト不要なのでケースから除外、という具合です。

**3）デシジョンテーブル**
ドメイン分割および禁則条件除外後の全組み合わせについてテストする場合、デシジョンテーブルというテスト手法（フォーマット）があります。

[入力データや入力条件の組み合わせを考える「デシジョンテーブルテスト」](https://webrage.jp/techblog/decision_table_testing/)

デシジョンテーブルのフォーマットは「それっぽく」見えるので、プロジェクトのテンプレートとして好んで使われることが多いようです。
しかし、執筆者の個人的見解ですが、デシジョンテーブルは以下のような弱点があると考えています。

- 条件がn次元の入れ子になると網羅性を確認しづらいため漏れを発生させやすい
- 「手順」が絡んでくるとフォーマットにハメ込みづらい
    - 例）手順1を行って項目AがXであることを確認し、次に手順2を行って項目AがYに変化することを確認する、というようなテスト

まず、デシジョンテーブルによるテストが最適解なのかを良く検討すべきです。
そしてデシジョンテーブルを採用するのであれば、形式だけにとらわれず、値の選択を慎重に行うべきです。

**4）ペアワイズ法（オールペア法）**
全ての組み合わせをテストすることが現実的に不可能なケースは多々あります。
このような場合に採用を検討すべき手法がペアワイズ法です。

[テスト工数を削減できるかもしれないペアワイズ法とPairwiser](http://qiita.com/y_hokkey/items/0a433ba25a5c5587d4ad)

ただし、統計的に導き出された「必要最小限の組み合わせ」ですので、リスクがあることは認識しておく必要があります。

## 3.4. （参考）ISO/IEC/IEEE 29119 で列挙されているテスト技法

- **仕様ベースのテスト手法：**
    - 同値分割
    - 分類ツリー法
    - 境界値分析
    - 状態遷移テスト
    - デシジョン・テーブル・テスト
    - 原因 - 効果グラフ作成
    - 構文テスト
    - 組み合わせテスト技法：
        - すべての組み合わせ
        - ペアワイズテスト
        - 各選択肢のテスト
        - 基本選択テスト
    - シナリオテスト（ユースケーステストを含む）
    - ランダムテスト

- **構造ベースのテスト手法：**
    - ステートメントテスト
    - ブランチテスト
    - 意思決定テスト
    - 以下を含む状態テスト
        - 分岐条件テスト
        - 分岐条件の組み合わせテスト
        - 変更条件判定条件（MCDC）のテスト
    - 以下を含むデータフローテスト
        - すべての定義
        - すべてのc-uses
        - すべてのp-uses
        - すべての用途
        - オールデュパス

- **経験ベースのテスト手法：**
    - エラーの推測

出典：[SoftwareTestingStandard.org](http://www.softwaretestingstandard.org/part4.php)
（日本語訳は執筆者）

# 4. テスト実施の心構え

> **重大なバグを素早く見つけよう**

- 変更していない箇所より修正した箇所を
- 周辺機能より先に基本機能を
- 特殊な条件より先に普通の条件で

> **「私の仕事じゃありません」と言ってはならない**
>
> **設計の不具合を検出するのもテストの目的**
>
> **「直した」と言われたら、別のところに問題が出てきていないか確認せよ**

- プログラムと仕様書の食い違いを見つけさえすれば良い、と思うべからず
- テスト仕様書に書かれているケース数を消化すれば良い、と思うべからず

> **障害レポートの価値を高めるための、手間暇を惜しむな**
>
> **バグの報告は新鮮さが大切**
>
> **障害レポートの処理コストにも注意を払え**
>
> **障害レポートはタイトルで決まる**
>
> **誰が読むかわからない。言葉使いには十分注意すること**
>
> **再現しないエラーも全て報告せよ。時限爆弾になる恐れがある**
>
> **障害レポートは1件1葉**

障害報告は、

- 速やかに
- 簡潔に
- それを読む人の立場に立って
- 広い視野で

行いましょう。

引用：[ソフトウェアテスト293の鉄則](https://www.amazon.co.jp/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%86%E3%82%B9%E3%83%88293%E3%81%AE%E9%89%84%E5%89%87-Cem-Kaner/dp/482228154X)（書籍）

# まとめ

テストは、知識と知恵を駆使して、戦略的に行うべき仕事です。
またテスト戦略に唯一絶対の正解は存在しません。

> 「どうすればより良いテストができるか」を常に問い続けよ

引用：[ソフトウェアテスト293の鉄則](https://www.amazon.co.jp/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%86%E3%82%B9%E3%83%88293%E3%81%AE%E9%89%84%E5%89%87-Cem-Kaner/dp/482228154X)（書籍）