テストタイプ
テストタイプは、目的に応じて異なり、機能的な品質(完全性、正確性など)だけでなく、非機能的な品質(信頼性、使用性など)も評価します。また、システム構造の確認や欠陥修正、変更による影響も確認します。この記事では、その基本的な概念を解説します。
1/機能テスト
機能とは「何をするか」を指し、「どのように動作するか」を意味するものではありません。機能テストの目的は、機能が仕様に従って正しく実装されているかを確認することです。
テストレベル
機能テストの対象には、システムやコンポーネントを統合したサブシステムなど、さまざまなものがあります。機能テストは複数のテストレベルで実施されます。コンポーネント仕様に基づく場合はコンポーネントレベルの機能テストとなり、システム仕様(ユーザーに提供する機能)に基づく場合はシステムテストレベルになります。
例えば、コンポーネントテストレベルでは機能テストが重要視され、システムテストレベルでは非機能テストがより重視されるなど、テストレベルによって焦点が異なります。
テスト技法
機能テストはソフトウェアの外部の動作や振る舞いを評価するため、ブラックボックステスト技法を使用します。これには、同値分割法、境界値分析、デシジョンテーブルテスト、状態遷移テスト、ユースケーステストなどが含まれます。
テストカバレッジ
機能テストのカバレッジは、機能の網羅性、すなわち機能カバレッジによって評価されます。これは、テストで実行した機能が全体のどのくらいの割合を占めているかを示します。システムテストレベルの機能テストのカバレッジは、実行された機能要件の割合で表されます。
ソフトウェアが解決する特定のビジネス問題
例えば、石油の探査では、いくつかの測定データをもとに石油が埋蔵されている可能性を推測します。この推測結果が地質モデルと呼ばれますが、地質モデルを作成するソフトウェアを開発するには、石油探鉱や油田開発のビジネスの仕組みについての知識が必要です。
ソフトウェアの役割
例えば、対話型コンピューターゲームでは、通常人間同士が行う机上ゲームの役割をコンピューターが担い、1人でも遊べるようにしています。さらに、コンピューターがユーザーと会話し、応答することもありますが、その会話がゲームの進行に影響を与えるため、適切な応答が求められます。テストを行うためには、ゲームのシナリオや、ゲームを楽しむために適切な会話内容を理解しておくことが重要です。
2/ 非機能テスト
非機能とは、文字通り「機能」以外の要素を指します。つまり、非機能は「どのように動作するか(How)」に関することであり、「何をするか(What)」ではありません。非機能テストの目的は、コンポーネントやシステムの特性、例えば性能、使いやすさ、セキュリティなどを評価することです。
テストタイプの例
非機能テストには、さまざまなテストがあります。例えば、性能テスト、ロードテスト、ストレステスト、ユーザビリティテスト、相互運用性テスト、保守性テスト、信頼性テスト、移植性テストなどがあります。
性能テスト (performance testing)
ソフトウェア製品の性能を判定するためのテストです。
負荷テスト (Load Testing)
性能テストの一種で、コンポーネントやシステムがさまざまな負荷状況でどのように動作するかを評価します。一般的に、想定される最低、通常、ピークの負荷を基準にテストを行います。
ストレステスト (Stress Testing)
性能テストの一つで、想定以上の負荷や、メモリやサーバーのリソースが不足している状態でシステムやコンポーネントの動作を評価します。
使用性テスト (Usability Testing)
特定のユーザーが特定の状況下でシステムを利用する際に、その有効性、効率性、満足度を測定するために実施されるテストです。
相互運用性テスト (Interoperability Testing)
複数のコンポーネントやシステムが情報を交換し、相互に利用できるかどうかを確認するためのテストです。
保守性テスト (Maintainability Testing)
ソフトウェアが意図した保守者によって修正や変更をどれだけ容易に行えるかを測定するためのテストです。
信頼性テスト (Reliability Testing)
コンポーネントやシステムが、指定された条件下で要求された機能を安定的に実行できるかを確認するテストです。
移植性テスト (Portability Testing)
ソフトウェアが異なる環境間で問題なく移行できるかを評価します。ここでの環境には、ハードウェア、ソフトウェア、または組織の違いが含まれます。
セキュリティテスト (Security Testing)
システムやデータが認可された権限内で正しく保護され、データへのアクセスが適切に制御されているかを確認するテストです。
テスト方法
非機能テストでは、ブラックボックステスト技法が活用できます。例えば、性能テストにおけるストレス条件を設定する際に、境界値分析が用いられる場合があります。
テストカバレッジ
非機能テストのカバレッジは、非機能要素がどの程度網羅されているかで評価します。例えば、モバイルアプリの非機能テストとしてデバイス互換性テストを実施する場合、定義された全デバイスの中でテストを実行したデバイスの割合によってカバレッジが測定されます。
特定のユーザーの知識
例えば、医療施設で使用される電子カルテシステムでは、患者の個人情報を安全に管理する必要があります。複数の看護師や医師が使用する際、不正に個人情報を閲覧できない仕組みを確保するために、利用状況やタイミングに応じたテストが求められます。
3/ ホワイトボックステスト
ホワイトボックステストは、システムの内部構造や実装を基にテストケースを設計するテスト手法です。このテストの目的は、コンポーネントやシステムの構造やアーキテクチャが正確で完全であり、仕様に従っていることを確認することです。
テスト技法
ホワイトボックステストは、ソフトウェアの構造がテストケースによってどの程度カバーされているかを確認するテスト手法です。このため、ホワイトボックステスト技法に分類される手法を使用します。
テストカバレッジ
ホワイトボックステストのカバレッジは、構造要素の網羅性(構造カバレッジ)で評価されます。コンポーネントテストやコンポーネント統合テストでは、ツールを用いてコードのカバレッジを測定します。一方、システムテストや受け入れテストでは、メニュー構造やビジネスモデルのカバレッジが測定対象となります。
コンポーネントテストレベルの例
コンポーネントテストでは、コードカバレッジを指標として使用します。これは、コンポーネント内で実行されたステートメントの割合を基に、テストの網羅度を評価するものです。
コンポーネント統合テストレベルの例
コンポーネント統合テストでは、コンポーネント間のインターフェースを構造要素とし、テストされたインターフェースの割合を基に網羅度を測定します。
必要となる知識
ホワイトボックステストの設計や実施には、以下のような専門的なスキルや知識が必要になる場合があります。
・コードのビルド方法:例えば、コードカバレッジツールを利用する際には、ソースコードファイルの構成やビルド手順に関する知識が必要です。
・データの格納方法:物理スキーマの配置に関する理解が必要で、これにより可能なデータベースクエリーを評価できます。
・カバレッジツールの利用と結果の解釈:ツールの適切な使用方法や、生成された結果を正しく理解するスキルが求められます。
4/ 変更部分のテスト
従来とは異なる観点からのテストタイプを紹介します。テストを実行して欠陥を発見した場合、修正後に再度テストを行う必要があります。同様に、機能の追加や変更によってシステムが更新された場合も、既存のテストを再実行する必要があります。その主な目的は以下の通りです。
・修正した欠陥が解消されていることを確認する
・機能が正しく動作していることを確認する
・予期しない悪影響が発生していないことを確認する
イテレーティブやインクリメンタル開発(例: アジャイル)では、新機能の追加や既存機能の変更、コードのリファクタリングが頻繁に行われるため、変更部分のテストが不可欠です。また、IoT(モノのインターネット)システムのように、デバイスの更新や交換が頻繁に行われる場合も同様に重要です。
変更部分のテストには以下の2種類があります。
・確認テスト:修正された欠陥が正しく解消されているかを確認するテスト
・リグレッションテスト:新たな欠陥が作り込まれていないか、また意図しない影響が発生していないかを確認するテスト
システムは常に進化を続けるため、確認テストとリグレッションテストは欠かせない重要なテストです。
確認テスト
確認テストは、欠陥を修正した後、この欠陥に起因する故障が再現しなくなることを確認するためのテストです。
確認テストでは、修正後のプログラムを再実行し、欠陥が解消されたことを確認します。場合によっては、新しいテストケースを追加して実施することもあります。ただし、確認テストは開発活動であるデバッグと混同しないよう注意が必要です。
リグレッションテスト
リグレッションテストは、すでにテスト済みのソフトウェアを繰り返し検証するテストです。これにより、変更によって生じた新たな欠陥や修正が原因で発生した別の問題、あるいは意図しない副作用を検出することを目的としています。
欠陥は修正されたコンポーネントだけでなく、関連する他のコンポーネントにも影響を及ぼす可能性があります。そのため、リグレッションテストでは実施範囲を適切に設定することが重要です。範囲の決定には、動作していたソフトウェアに欠陥がある場合のリスク(プロダクトリスク)を考慮します。
また、ソフトウェアの動作環境が変更された場合や、新しいOSやデータベース管理システムなどに移行した場合にもリグレッションテストが必要です。いつでも迅速にテストを実行できるよう、適切なテストスイートを整備しておくことが求められます。
メンテナンス(保守)テスト
ソフトウェアやシステムの開発が完了し、本番環境にリリースまたはデプロイされた後は、メンテナンス(保守)が必要になります。ソフトウェアやシステムは数年から場合によっては数十年にわたり使用され、その間に機能の追加、変更、削除が繰り返し行われます。また、動作環境の変化に応じた改修も必要です。さらに、開発中に徹底的なテストを実施しても、リリース後に欠陥が見つかることは避けられず、それらの修正も求められます。このように、メンテナンス期間中には多様な変更が生じます。
これらの変更に対応して行うのがメンテナンステストです。メンテナンステストの主な目的は以下の2つです。
・変更が正しく反映されていることを確認する
・システムの変更していない部分に意図しない影響(リグレッション)がないことを確認する
メンテナンス期間中には、ソフトウェアのバージョンやリビジョンを更新するリリースが複数回行われます。これには、計画的な機能追加を伴うリリースと、欠陥修正のための緊急パッチ提供などの非計画的なリリースの両方が含まれます。いずれのリリースにおいてもメンテナンステストは欠かせません。
メンテナンステストでは、機能テストだけでなく非機能テストも実施する必要があります。たとえば、性能向上を目的とした変更が行われた場合、性能テストを行うのはもちろんですが、機能の変更によって性能が低下していないことを確認することも重要です。すべてのケースであらゆるテストタイプを実施する必要はありませんが、変更がどの品質特性に影響を与える可能性があるかを考慮し、適切なテストタイプを選ぶ必要があります。
また、複数のテストレベルを組み合わせて実施することも求められます。たとえコードの一部をわずかに修正するだけの場合でも、コンポーネントテストに加え、そのコードが関連する他のコードとのインターフェースを確認する統合テストや、システム全体の動作を確認するシステムテストが必要になる場合があります。変更の影響範囲を十分に評価し、必要なテストレベルを決定することが重要です。
メンテナンステストで実施するテスト範囲を決める際の主な要因は以下の通りです。
・変更のリスクの度合い:変更箇所が他のコンポーネントやシステムと参照やデータ交換を多く行う場合、テストの必要性が高まる
・既存システムの規模:システムが大規模であるほどテスト範囲が広くなる可能性がある
・変更の規模:修正内容が広範囲にわたる場合、より多くのテストが必要となる
メンテナンスが必要となる理由
メンテナンステストが必要となるケースには、以下のような状況があります。
ソフトウェアの変更が行われた場合
計画的な機能拡張や仕様変更、欠陥修正など、ソフトウェアに手を加えた際には、その変更が適切に反映されているかテストが求められます。
運用環境に変更が生じた場合
対象ソフトウェアそのものに変更がなくても、OSやデータベース、COTSソフトウェア(商用ソフトウェア)のバージョンアップやパッチ適用といった運用環境や周辺システムの変更があれば、ソフトウェアの動作確認が必要です。
新しい環境への移行が行われた場合
例えば、異なるプラットフォームへの移行時には、移行後の環境で正しく動作するかを確認する必要があります。また、他のアプリケーションからデータを移行する場合には、データ変換が正確に行われたかを確認するテストも不可欠です。
ソフトウェア廃棄時
ソフトウェアの利用を終了する際に、使用していたデータを保管する必要がある場合、データ移行や保管作業のテストが求められます。また、保管されたデータが正しくリスト化されたり、必要に応じて抽出できることを確認するテストも必要です。
IoTシステムでは、多数のソフトウェアやデバイス、サービスが相互に連携するため、メンテナンステストは非常に重要であり複雑です。既存システムのデバイスやソフトウェアの変更、新規追加の際には、それらをシステム全体に統合する統合テストが不可欠です。さらに、個人データを扱う場合は、連携された新しい要素がデータを不正利用したり、漏洩させたりしないよう、厳密に確認する必要があります。
メンテナンスの影響度分析
前のセクションで述べたさまざまなメンテナンス作業を実施し、ソフトウェアやシステムをリリースする際には、それぞれの作業(変更、追加、削除など)がもたらす影響を調査する必要があります。この調査は「影響度分析」と呼ばれます。影響度分析で特に難しいのは以下の2点です。
・変更による副作用(リグレッション)
・変更が影響するシステム領域の特定
影響は予想外の場所に現れることがあり、その場合、リグレッションテストを実施しないと、リリース後に不具合が発生する可能性があります。そのため、変更による影響範囲に対してリグレッションテストを実施することが非常に重要です。
リグレッションテストでは、影響を受けた範囲に関連する既存のテストケースを実行するだけで済む場合もあります。しかし、変更内容によっては、既存のテストケースの修正や新たなテストケースの追加が必要になることがあります。例えば、ある関数に引数を追加する変更があった場合、既存のテストケースは従来の2つの引数に対する入力値しか含まれていないため、追加された引数にも適切な入力値を設定する必要があります。また、テスト自動化を行っている場合、自動テストスクリプトの修正も必要になることがあります。リグレッションテストを効果的に行うためには、メンテナンス作業を事前に正確に見積もることが重要です。
変更後に影響度分析を行うこともありますが、変更前に影響度分析を行うことで、作業量を予測し、必要な作業を計画することができます。また、影響の大きさや範囲によっては、影響を最小限に抑える変更方法を再考することも有効です。
影響度分析を効率的かつ正確に行うためには、テスト対象のソフトウェアアイテムとテストウェアの間でトレーサビリティを確立しておくことが重要です。さらに、テスト対象ソフトウェアの保守性を高めておくことも必要です。一般的には、モジュールの凝集度を高く保ち、結合度を低くすること、コードクローンを共通化すること、リファクタリングを行うことなどにより、コードの構造をきれいに保つことが推奨されます。
これらの取り組みが行われていない場合、以下のような状況では影響度分析が難しくなることに注意が必要です。
・仕様が最新でない、または存在しない
・テストケースが文書化されていない、または最新版でない
・テストケースとテスト基盤との間で双方向のトレーサビリティが確保されていない
・ツールによる影響度分析のサポートが不十分、もしくは存在しない
・ドメインやシステムに関する知識を持った担当者がいない
・開発時にソフトウェアの保守性が考慮されていない
※確認テスト: