コラム
ソフトウェア開発において、テストの実施は品質を担保するうえでも重要な工程です。 ソフトウェアテストは確認対象の粒度によって以下の4つの段階(レベル)に分けることができます。
・コンポーネントテスト(単体テスト、ユニットテスト)
・結合テスト
・システムテスト
・受け入れテスト
本記事ではそのような「コンポーネントテスト」に注目し、重要な考え方と実施の際に気をつけるべきポイントについてご紹介します。
コンポーネントテストとは、テスト工程の最初に実施されるテストです。
会社やチームによっては、単体テスト、ユニットテストと呼ばれる場合もあります。「コンポーネント」は「構成要素」「部品」などの意味をもち、ソフトウェアテストにおいては独立してテストできるソフトウェアの最小単位を指します。
コンポーネントテストでは、ソフトウェアの各機能や画面などが単体で適切に動作するか検証します。
例えばECサイトの購入ページを例にあげてご説明します。
購入ページには、以下のようにさまざまな機能が組み込まれています。
・商品Aの金額が表示される(処理1)
・金額の合計が表示される(処理2)
・金額の3桁目にカンマが入って出力される(処理3)
このような特定の処理の流れを構成するひとつひとつの動作が行われるかを確認します。
コンポーネントテストを実施するうえで、課題を抱えている会社やチームも存在します。
各ソフトウェアの動作をひとつひとつ確認する必要があるため、プロジェクトの規模が大きくなればなるほど大きな負担が生じます。スケジュールに余裕がなくなったりリソースが不足してしまったりすることにより、不完全なテストになってしまう可能性もあります。
前述の通りコンポーネントテストは、テスト工程のなかで最初に実施します。独立した機能が仕様通りに動作するか、仕様に漏れがないかなどをテスト工程の早い段階で確認することは、後のテストレベルでの手戻りをなるべく少なくするために重要です。
コンポーネントテストで発見された不具合は確認範囲が限定的なため、開発者がどのソースコードに問題があるか把握しやすいという特徴があります。これは、ソフトウェアの不具合を修正するために必要となるコストを抑えることにも効果的です。
出典:株式会社SHIFT、日経BP「駄目パターンに学ぶ 失敗しない ソフトウェアテスト 実践ノウハウ」114ページ 図3 「V字モデルを用いたテストレベルの説明」を基に作図
ソフトウェアの品質を保つためには、各開発工程に対して行うテストを明確にしておく必要があります。V字モデルを参考にできるプロジェクトであれば、漏れなどを減らすことができます。
V字モデルとは、開発の上流工程とテスト工程を対に並べたモデルです。上流工程ですり合わせた粒度を流用できるため、共通の認識が得やすくなります。
V字モデルにおいて、コンポーネントテストは詳細設計と対になります。
「画面遷移」を例にあげてご紹介します。例えばECサイトにおける、商品の購入確定前の画面にて名前や住所などを入力することを考えた場合に、
・入力内容に漏れがあった場合は画面Aに遷移する
・入力内容に漏れがない場合は画面Bに遷移する
のように詳細設計まで言及されている場合、コンポーネントテストでは仕様書に記載されている画面へ正しく遷移するかまで検証を行います。
改めてコンポーネント以外のテストレベルでテストしたい領域を確認してみましょう。
結合テストは、コンポーネントテストの後に実施されるテストレベルです。
機能ごとに動作するようになった部品を組み上げてから、一連の機能が動作するかどうか確認します。
ユーザー認証の一部を例にあげてみましょう。
・入力フォームが表示される(画面X)
・パスワードが伏せ字で表示される(機能A)
・パスワードが一致した場合認証に成功する(機能B)
このように「画面⇒機能A⇒機能B」を一括りにして表示やデータの入力が仕様通りに動作するかテストを行います。
システムテストでは、あらかじめ実務で想定されるようなシナリオを設計しておく必要があります。そのうえで実際に本番環境で使用するハードウェアを利用したり本番と同等の環境で動作させながら行います。
例えば、ユーザーがパスワードを忘れてしまったと想定しテストを行ったり、実際にアクセスが集中することを想定して負荷をかけるなどのテストを実施します。
受け入れテストは、ユーザー側の観点で行うテストです。システムの発注者側で実際のビジネスでソフトウェアが運用できるかどうかを確認します。
具体的には、エラーのメッセージが後続の業務の遂行に与える影響があるかといった、業務レベルの検証を行います。
テストタイプ別にコンポーネントテストを実際に実施する例をご紹介します。
テストタイプとは、テストで確認したい目的別に分類したものです。一般的によく用いられる代表的なテストタイプは以下の6種になります(テストタイプはさまざまなものがありますが、ここでは一部を紹介しております)。
・機能テスト
・疎通テスト
・性能テスト
・回帰テスト
・セキュリティテスト
・ユーザビリティテスト
コンポーネントテストでは、機能テストを中心に行います。
また、プロジェクトによって優先度が変わりますが、「疎通テスト」「性能テスト」「セキュリティテスト」を行う場合もあります。
反対に、「回帰テスト」「ユーザビリティテスト」はテストの性質上コンポーネントテストのなかでの実施には向いていないこともあります。
なぜなら最小のコンポーネントに不具合がある場合、コンポーネント同士の依存や関連についてテストを行っても、不具合が生じることは明白なためです。そのため、依存や関連によってテストの確認箇所が大きくなる場合はコンポーネント自体の設計を見直すか、コンポーネントテストではなく後のテストレベルで、テストを実施することが望ましいといえます。
これらをふまえて、それぞれのテストタイプを確認してみましょう。
ソフトウェアの機能が、上流工程やプロダクトマネージャーが決めた仕様通りに動作するか検証するテストです。
金額を表示する際、数字の3桁目にカンマを入れるという仕様の場合、インプットが「1000」の時アウトプットが「1,000」になるかどうか、インプットが「100」の時アウトプットが「100」になるかどうかというようなテストを行います。
細かいテストケースの実行が求められるため、自動化を行うケースも多くあります。
システム間でリクエストとレスポンスが成立するかどうかを検証するテストです。
例えば、ネットワークを経由するシステムA、システムBでデータの行き来ができるか確認するようなテストが該当します。
コンポーネントテストではソフトウェアの各機能や画面などを単体でテストを行うため、ネットワークを経由して確認するテストを求められるケースは少ないことが一般的です。
実際に行うケースでは、まずは特定のシステムのプログラム内で関数と関数のデータの入出力ができるかどうかといった小さい単位での疎通や、関数からデータベースへアクセスできるかといった確認を行います。
もし未制作の処理がある場合は、モックやスタブといった「値を受け取るだけのダミー処理」「値を返すだけのダミー処理」を用いて仮想的にデータの確認をします。
実際のユーザーの利用に耐えられるかどうか検証を行います。
ユーザーが実際にソフトウェアを利用した際に、ハードウェアに対する負荷や処理が完了するまでの必要時間をテストします。
主にデータを集計する部分などデータ量を増やしたときに、影響を受けそうな箇所を中心にテストを実施します。
回帰テストは、リグレッションテストや退行テストとも呼ばれます。
システムが複雑になってくると変更を行った場所とは別のところに影響が出るケースもあるため、システムの改修を行っていない部分に不具合が発生しないか(デグレ)検証するテストです。
コンポーネントテストでは、回帰テストが必要なほど大きな単位が割り振られるケースはあまり多くないことが一般的です。回帰テストが必要になった場合は、そもそもコンポーネント自体の設計を見直すことをおすすめします。
悪意のあるユーザーにシステムが攻撃されても大丈夫かどうか、検証を行うテストです。パラメータに対して、攻撃コードを入れて実行します。セキュリティテストは、必ず本番で使用するデータから切り離された環境で行ってください。
ソフトウェアに不正なSQLの文字列が入力されるなどの攻撃が行われた場合、ソフトウェアが正常に不正を発見し攻撃に対処できるか確認します。
ただし、後のテストレベルでテストを行うことが多いため、コンポーネントテストにおいてはセキュリティテストを優先的に行うケースは多くないでしょう。
ソフトウェアで実際に業務を行ったり、シナリオを想定してユーザーの操作感や使用感などを検証したりすることなどが、ユーザビリティテストです。
コンポーネントテストでは、各機能や画面などが単体で適切に動作するかなどひとつひとつの処理を確認することが目的であるため、複数の機能が組み合わされた実際の操作感や使用感などを検証するユーザビリティをテストするには向かないケースが多いでしょう。
ソフトウェアテストは4つのテストレベルに分割されますが、なかでもコンポーネントテストはテスト工程の最初に実施される工程です。確認する機能や範囲も限定的になるため、不具合を発見した場合の原因特定も他のテストレベルよりも比較的容易です。そのため、コンポーネントテストで仕様通りに動くか、仕様の考慮漏れがないかどうかを明確にすることで、後の工程で手戻りの発生を防ぐことにつながります。
ソフトウェアテスト全体の高品質化とコストの肥大化防止のためには、コンポーネントテストでできるだけ網羅的かつ効率的にテスト実行をすることが重要です。