ソフトウェアの品質を高めるためには、テスト工程だけで品質向上を図ろうとするのではなく、開発の段階からテスト工程を見据えて取り組むことが重要です。
本稿では、テスト工程の生産性に直結する「テスタビリティ」の概念と、実際にテスタビリティの高いシステムを作り上げるために留意すべき点についてご紹介します。
テスタビリティとは
テスタビリティ(Testability)とは、テスト容易性・テスト実行可能性と訳されます。つまり、テストが実行しやすいか、必要なテストが十分実施できるか、を表すものです。
テスタビリティが高いということは、必要なテストが実行しやすく、不具合が見つかりやすいということになります。
一方、テスタビリティが低いと、そもそもテスト実行が不可能だったり、実現できたとしても膨大なコストが発生したり、または、限られた方法でしかテストができないために不具合検出率が低くなる、ということが起こります。
テスタビリティのさまざまな指標
テスタビリティ、すなわちテスト容易性・実行可能性を評価する指標は1つだけではなく、複数の指標を用いて多角的に評価するものです。ここでは、テスタビリティの代表的な指標として、James Bachが提唱したテスタビリティの品質モデルをご紹介します。
テスタビリティの品質モデル
実行円滑性(Operability)
テストを円滑に実行できるかどうかを測る指標です。例えば、テスト実行中にテストを妨げるようなバグが発生しにくいことなどが挙げられます。
観測容易性(Observability)
テスト対象の出力内容や発生するエラー・不具合を確認しやすいかどうかを測る指標です。例えば、エラー発生時にテスト実行者がそのエラーを検知しやすいことや、システムの内部ステータスを外部から取得する手段があることなどが挙げられます。
制御容易性(Controllability)
テストを行う際の操作や制御がしやすいかどうかを測る指標です。
例えば、テスト対象の内部ステータスをテスト内容に合わせて操作可能であることなどが挙げられます
分解容易性(Decomposability)
テスト対象のシステムに関して、テスト対象とする範囲やテストを実行する範囲を分離しやすいかどうかを測る指標です。例えば、テスト対象が依存するコンポーネントをスタブやモックによって置き換えが可能であることが挙げられます。
単純性(Simplicity)
テスト対象のコードの構成や機能仕様のシンプルさを測る指標です。例えば、不要な処理の呼び出しや冗長なコード構成になっていないことが挙げられます。
安定性(Stability)
テストの設計・実行負担を増やすようなシステムの変更が少ないかどうかを測る指標です。例えば、インターフェースの仕様変更が少ないことや設計方針の転換が起こりにくいこと、発生したとしてもテストの設計内容を修正するコストが低いことなどが挙げられます。
理解容易性(Understandability)
テストを設計するにあたって、必要なテスト対象の情報を引き出しやすいかを測る指標です。例えば、内部構造を熟知せずともAPI仕様などの情報を理解しやすいことが挙げられます。
テスタビリティと信頼性
上記で挙げたJames Bachが提唱したテスタビリティの品質モデルは、主にテストの実施段階でのものと言えるでしょう。この他に、テスタビリティは信頼性の面でも着目されることがあります。
例えば、人工衛星のソフトウェアなどの高品質が求められるシステム開発では、その設計方式に応じ、必要とされるテストが十分実施できるかどうか厳密にレビューされます。
レビューの結果、その設計方式では十分なテストができないという結論に至った場合は、その設計内容は廃案になり、再設計を行うこともあります。
テストのしやすさとソフトウェア構造の関係
以上で述べたように、テスタビリティとアーキテクチャレベルでのソフトウェア構造は密接に関連しているため、開発段階から「テストのしやすさ」を考慮して設計する必要があります。
自動テストを例にとってもう少し詳しく説明しましょう。
自動テストはテスト品質を上げるための1つの選択肢ではありますが、自動テストを導入する際は、テスタビリティの高いシステム構造になっていることが前提となります。
テスタビリティが低い場合、自動テストの導入が困難になったり、システム改修のたびに自動テストを大きく作り変えたりして、品質を維持するためのコストが高くなったりすることもあります。
したがって、自動テストを導入する際は、自動テストの環境を構築するよりも前に、テスト対象のシステムをアーキテクチャレベルでテスタビリティの高い設計に見直すことが必要となります。
テスタビリティ向上のための開発ポイント
テスタビリティを向上させるために設計で留意すべき点は、「制御点」「観測点」「接合部」の3つが挙げられます。以下では、それぞれの概念の特徴をご紹介します。
制御点(Control Point)
テスト対象箇所の操作性に着目した概念で、制御容易性を高める実装です。この観点においてコードレベルのテスタビリティを実装するには、例えば、APIを利用した入力制御を行う・デバッガで変数の中身を書き換えるなどが挙げられます。
観測点(Observation Point)
テストを行う対象の出力内容に着目した概念です。テスト対象の出力内容を取得する手段として、APIによる出力やテストスパイを活用した出力内容と期待値の比較などの実装が挙げられます。
接合部(Object Seam)
テスト対象となるコンポーネントと別のコンポーネントが関連し合うポイントに着目した概念です。テスト対象を切り分けることで、分解容易性や実行容易性が向上します。実装においては、変数やクラスをコンポーネントの外から動的に与えられるようにする「依存性の注入(Dependency Injection)」といった手法がその一例です。
テスタビリティ向上の効果測定と継続的改善
テスタビリティ向上の効果の測定対象は、第一に、テスト実行の生産性はどの程度向上したか、自動テストのカバー範囲がどれだけ拡大できたか、などが挙げられます。
この他にも、テスタビリティ向上を目的とした施策は、テストエンジニアだけでなく開発エンジニアにとってもプラスの影響を与えます。例えば、デバッグがしやすくなる、同じテストを繰り返し活用できるなど、開発にかかる手間を減らす効果が期待できるため、これらもテスタビリティ向上による効果の測定対象にすると良いでしょう。
また一方で、テスタビリティ向上の施策は、場合によってはパフォーマンスの低下とトレードオフの関係にあることもあるので注意が必要です。例えば、観測容易性を向上させるためにログを出力させることで特定の処理の速度劣化が発生するような場合があり、全体のバランスに気を配ることが必要です。
テスタビリティを向上させる施策の効果は、開発サイクルを繰り返すうちにソフトウェアアーキテクチャが変化することで、効果が薄れることもあります。
このように、テスタビリティ向上によりどんな効果が得られたか、開発サイクルを繰り返すたびに効果を確認し、継続的に見直して最適化し、改善を施していくことが必要です。
テスタビリティ向上の施策がもたらすシステムへの影響と期待できるコスト削減・品質向上の効果などの評価は、開発の全体を通じて行うようにしましょう。
おわりに
本稿では、テスタビリティの概念と、評価指標、テスタビリティとソフトウェア構造との関係を解説しました。
開発プロセス全体の要となるテスタビリティの概念を導入し、ソフトウェア開発の全体的な生産性の向上、そして製品の品質と信頼性の向上につなげましょう。
参考URL
- 連載 [第8回] : 開発現場で役立つテスト「超」実践講座「テスタビリティ」を作り込む|ThinkIT
(https://thinkit.co.jp/article/14136)
- テスト容易性のためのシステム設計|InfoQ
(https://www.infoq.com/jp/news/2014/11/designing-systems-testability)
- JaSST'11 Tokyo B5-2 テスト技術に基づく設計品質定量化の取り組み|株式会社NTTデータ
(http://www.jasst.jp/archives/jasst11e/pdf/B5-2.pdf)
- テスト自動化の品質モデルの扱い|SlideShare
(https://www.slideshare.net/goyoki/ss-36405244)
- テストダブルの種類|Qiita
(https://qiita.com/k5trismegistus/items/94599074a961074d9237)