ソフトウェアテスト

ソフトウェアテスト (Software testing) は、コンピュータのプログラムから仕様にない振舞または欠陥（バグ）を見つけ出す作業のことである。ソフトウェアテストで見つかったプログラム中の欠陥を修正する作業をデバッグという。ソフトウェアテストに成功するとは、テストで欠陥が発見されるか、規定した試験項目にすべて合格するか、規定した品質目標に到達することである。目標とした品質には、規定した試験項目にすべて合格することもある。例えば、OS, プログラミング言語では、仕様を満たしているかどうかの適合試験を規定している。ソフトウェアテストでは、欠陥が存在することを示すことはできるが、欠陥が存在しないことは証明できない。ソフトウェアに仕様にない振舞がないことを保証する作業を証明といい、証明用のシステム、証明しやすい言語も多数存在している。本項では動的なソフトウェアテストを中心に扱う。

動的テストと静的テスト

プログラムを実際に動かしてみて行うテストを動的テストと呼び、プログラムを実際に動かしてみることなくソースコードやオブジェクトコードを検証する作業を静的テストと呼ぶ。静的テストには、ツールを用いた静的コード解析の他に、人手で行うコードレビュー、ウォークスルー、インスペクションなどがある。多くの場合、意識されることはないが、コンパイラまたはプリコンパイラはソースコードを静的にテストする。

性能試験と機能試験

機能試験・性能試験の指標と分類にISO/IEC 9126 (ISO 9126) の枠組みを利用することがある。

機能試験 (function test)

機能試験は、規定した機能を果たすかどうかを試す。
関数であれば、規定した引数を与えると、想定した戻り値を返すブラックボックス試験が機能試験に相当し、単体試験の一部である。
適合試験、単体試験は、機能試験を主とするが、性能試験を含むことがある。

性能試験 (performance test)

性能試験は、ソフトウェアシステムの性能を測り、必要な性能が出ることを確かめる試験である。入力をどれだけ受付けるか、どれだけの出力が可能か。通信経路数・通信速度、処理件数などプログラム単体では問題が発生しなくても、通信、データベース、入出力 (I/O)、同時に起動するソフトウェアなどの高負荷、長時間使用などの条件下では性能が低下することがある。性能を確認する試験は、システムの性能に影響を与えないように測定する必要があるため、OSやミドルウェアなどでは性能を測定する効率的な計測方法を提供していることもある。
性能試験は、単体試験から実施する場合と統合試験から実施する場合とがある。
過負荷に対する性能試験をストレステストという。

ストレステスト

ストレステストは、ソフトウェアシステムに対して高い負荷を与え、処理の低下・抜け、データの破壊、発熱など致命的な問題が、どういう条件で発生するかを試験する。ストレステストを行うことで、高い負荷が加わっている状況でしか発生しない不具合や、発生確率の低い欠陥、著しい性能の低下を発見することがある。性能試験の一部として実施し、対応可能な付加の仕様を確かめることがある。

検証試験と妥当性確認試験

仕様通りに動いているか、試験仕様に基づいて確認する試験を検証試験 (verification test)、エンドユーザーの意図通りに動いているかどうかを確認する試験を妥当性確認試験 (validation test) という。

検証試験 (verification test)

決めた仕様に合致しているかどうかを試す試験。プログラミング言語、OS、通信規約、データベースなどの仕様に合致しているかどうかを試す試験を適合試験ということがある。

適合試験 (conformance test)

OS、プログラミング言語、ネットワーク通信プロトコル、データベースなどソフトウェアを動かすための基本的なプラットフォームが、仕様に適合しているかどうかを確認する検証試験 (verification test)。OSの国際規格の一つであるPOSIXでは、 NIST が適合試験のソースコードを公開している。
自動車用OSの国際規格OSEKでは、MODISTARC (Methods and tools for the validation of OSEK/VDX based distributed architectures) がある。
TOPPERS OSでは、TTSP (TOPPERS Test Suite Package) というテスト環境を提供し適合テスト等を実施しやすくしている。
プラットフォームの適合試験を実施せずに、アプリケーションソフトウェアの試験を実施すると、プラットフォーム仕様の変化に対応できていないことがある。

妥当性確認試験 (validation test)

エンドユーザーが意図している動作をするかどうかを試験することを妥当性確認試験という。
性能試験、システム試験、受入試験の一部として実施することがある。

上から (top down) と下から (bottom up)

全体が完成してからテストをすることをビッグバンテストという。規模の小さなプログラムであれば、この手法でうまくいく場合もある。この手法は大規模なプログラムに対して適当でない。なぜなら、大規模なプログラムを一気にテストをして問題が発生したときに、問題の原因を巨大なプログラム中から探すのが困難だからである。また、ソフトウェア中に複数のバグが存在する場合、それらのバグが相互に影響しあい、バグの原因の特定がさらに困難になる場合もある。そのため、ソフトウェアテストでは、最初に単体テストによってモジュール単位のテストを行う。単体テストの問題で、十分にモジュール単位のテストが終わったら、結合テストまたはシステムテストに進む。また、小規模なプログラムであっても、単体テストを行わずに結合テスト又はシステムテストへ入るのはテスト全体の効率を下げる。しかし、再利用性が高く、時間についての制約だけが中心の試験の場合は現場でビッグバンテストを行う場合がある。

ホワイトボックステストとブラックボックステスト

プログラムの内部構造に注目したテストをホワイトボックステスト (white box test)、プログラムの入力と出力に注目したテストをブラックボックステスト (black box test) という。

ホワイトボックステスト (white box test)

ホワイトボックステスト (white box test) は、プログラムの構造に着目したソフトウェアテストのことである。着目する構造には命令や分岐などがあり、注目した構造に対してどれだけの割合の部分を実行できたかを網羅率で表す。
1 int abs(int x) {2   if (x < 0) {3     x = -x;4   }5   return x;6 }

命令網羅 (statement coverage) (C0)

命令網羅基準を用いてテストを行う場合は、すべての命令を実行すればよい。上記のabs関数では、x = -1 を用いてテストすれば命令網羅基準に従ってテストできたことになる。

分岐網羅 (branch coverage) (C1)

判定条件網羅 (decision coverage) とも。分岐網羅基準を用いてテストを行う場合は、すべての分岐において、すべての分岐の方向を実行すればよい。上記のabs関数では、x = -1とx = 0を用いてそれぞれテストすれば、分岐網羅基準にしたがってテストできたことになる。分岐網羅は命令網羅の基準を満たす。

判定条件／条件網羅 (decision/condition coverage)

判定条件／条件網羅基準を用いてテストを行う場合は、各々の個別条件について全ての結果を少なくとも1回はとるようにし、かつ各々の分岐について全ての分岐の方向を実行すればよい。

複合条件網羅 (multiple condition coverage)

複合条件網羅基準を用いてテストを行う場合は、それぞれの判定における全ての結果の全ての可能な組み合わせを少なくとも1回はとるように実行すればよい。ただし、ある組み合わせは作ることが不可能である場合がある。たとえば、条件 (A > 2) と (A < 10) とでは、可能な組み合わせは3つしかない。

経路網羅 (path coverage)

経路網羅基準を用いてテストを行う場合は、すべての経路が少なくとも1回はとるように実行すればよい。反復構造を持つプログラムの全ての経路を特定することは普通は不可能であるから、この場合、完全な経路網羅は実行可能な目標とは考えられない。

ブラックボックステスト (black box test)

ブラックボックステスト (black box test) は、プログラムの入出力だけに注目し仕様通りにプログラムが動作するか（もしくは仕様通りに動作しないか）をテストする。プログラムの入力が単一の値である場合は同値分割や限界値分析を、プログラムの入力が複数あり相互に影響を与えるような場合は決定表や原因結果グラフなどを用いて入力を決定する。大域変数の読み書き、通信、割り込みなどが処理中にある場合には、それらも入出力の一つとして扱う。

同値分割

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

限界値分析（境界値分析）

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

単体試験 (unit test)

単体試験 (unit test) は、関数、メソッドなどの小さな単位で行うテストのことである。単体テストは、関数の場合には基本はブラックボックステストである。ブラックボックステストが済んだものの品質を確保するためにホワイトボックステストを行う。「Unit Testing」の略である「UT」と呼ぶことがある。また、開発現場によっては「CT（和製: Coding Test）」や「PT（和製: Program Test）」と略すこともある。
単体試験の道具としてJavaではテスティングフレームワークJUnitが有名である。これはJava専用である。他の言語にも同様のものがあり、それらを総称してxUnitと呼んでいる。

統合試験 (Integration Testing)

統合試験 (integration testing) は、単体試験が完了したプログラムを組み合わせて行う試験である。プログラムのどの部分から組み合わせていくかで、トップダウンテスト (top down test) とボトムアップテスト (bottom up test) に分けることができる。「Integration Testing」の略である「IT」と呼ぶことがある。また、結合テストと呼ぶ場合もある。
統合試験とシステム試験を分ける場合もある。統合試験とシステム試験を分ける場合に、模擬試験 (simulation) を統合試験に分類する場合と、システム試験に分類する場合がある。

システムテスト (system testing)

プログラムを単独ではなく、他のプログラムやハードウェア、通信ネットワーク、データベースなどと組み合わせて実施するテスト。開発環境と実行環境が異なる場合には、実際の実行環境を使って行うこともある。顧客にしか実際の実行環境がない場合には、顧客環境で行う場合がある。実際の環境を利用することが高価であったり時間がかかる場合には、模擬試験環境 (simulator) を作成して実施することがある。この場合には、模擬環境のシステム試験、実環境でのシステム試験と区分する。模擬環境では、複数の事象を同時に発生させることが難しかったり、逆に実環境ではありえない事象を発生させることができなかったり、それぞれの短所・長所を見極めて試験を実施する。エンタープライズ系と組込みソフトウェアで本質的な違いがあるわけではなく、OS、言語、ネットワーク、データベース、接続機器数の違いが大きい。

受入試験 (acceptance test)

受入試験 (acceptance test) は、検収テスト、承認テストとも呼ぶこともある。受入試験は、システムを受け入れるかどうかを判定する試験である。システムの実際の利用者が行う場合と受け入れ試験をシステム運用・保守会社が実施する場合がある。システムが仕様通りの機能や性能を備えているかどうか確認する検証試験だけの場合と、システムが利用者の意図通りに動くかどうかを確認する妥当性試験を含む場合がある。

アルファテスト、ベータテスト

完成前のソフトウェアを開発者以外に利用してもらい、欠陥を発見してもらうテストのこと。アルファテストは、ベータテストよりも完成度の低い段階（アルファ版）で行うテストである。アルファテストは内部で、ベータテストは外部でという区分をすることがある。オープンソース、オンラインゲームにおいては、ベータテストを広く一般に公開し、宣伝の目的も兼ねて実施する場合がある。ベータテストで配布するソフトウェア（ベータ版）は、基本的には製品版と同等の機能を備えるが、不具合が存在する可能性があるため、利用に際して注意すべきことが注意書きなどに記載している。設計側が予期していない不具合が発生することもあり、注意書きにないことで何を考えなくてはいけないかを想定し、システムのバックアップなどを実施してから導入することを基本とするとよい。

テスト代替 (Test Doubles)

単体テストや結合テストを行う際に、テスト対象のプログラムを呼び出すためのプログラムや、テスト対象のプログラムが利用しているプログラムがまだ使えない（もしくは、テストが完了していないため使うべきでない）場合がある。このような場合に、テスト対象のプログラムを呼び出すためのプログラムをテストドライバ (test driver)、テスト対象のプログラムが利用しているプログラムの代替となるプログラムをテストスタブ (test stub) という。
int isCompositeNumber(int x) {
  return !isPrimeNumber(x);}
上記のプログラムは、与えられた値が合成数かどうかを判定するプログラムである。このプログラムをテストするために必要なテストドライバとテストスタブの例を示す。

テストドライバ

int main() {
  int num;
  for (num = 2; num <= 10; num++) {
    if (isCompositeNumber(num)) {
      printf("%d is a composite number", num);
    } else {
      printf("%d is not a composite number", num);
    }
  }}

テストスタブ

int isPrimeNumber(int num) {
  return (num == 2) || (num == 3) || (num == 5) || (num == 7);}
このテストスタブは与えられた値が素数かどうかを判定するプログラムとしては明らかに不完全であるが、テストドライバから実行する範囲においては正しい挙動を示すので、指定した範囲でのテストスタブとしては十分な場合がある。しかし実行範囲が変わったときに直し忘れる可能性があるため、テストスタブ名に実行範囲を示す文字を入れる場合がある。

回帰試験 (regression test)

プログラムを修正・変更した場合に、過去に実施したテストを再度実施することを回帰試験 (regression test) 又は退行テストという。修正前の試験に再度合格するかどうか、他の機能に影響与えていないかどうか、他の機能が動作するかどうかを確認する。過去のテスト資産を使い、実施する回数も多いことから、実施を省略することがないようにテスト自動化することにより効率化を図る。

再現試験 (repeatability test)

再現試験 (repeatability test) は、初めて起きた現象・実験結果を確認する追試と、事故・不具合を再現し対策を立てるために実施することがある。

統計的手法

ソフトウェアが複雑になり、機能、関数の数が千以上になってくると、性能試験、機能試験の結果を統計的に処理し、どういう試験を実施するとよいかを統計的に検討することがある。また、テストでは、欠陥が存在することを示すことはできるが、欠陥が存在しないことは証明できないため、いつソフトウェアテストを終了すればよいかを決定するための基準として統計的手法として信頼度成長曲線等を利用する場合がある。信頼度成長曲線を利用する場合には、条件の変化を統計的にうまく扱わないと見落としが発生するか、無駄な作業を続けることがある。