リグレッションテストの方針の重要性
ソフトウェアに変更を加えた際に、意図せず変更とは関係のない所で故障が発生したり潜在的なバグが顕在化したりしたものは、リグレッション(和製英語でデグレードとも)と呼称されます。
リグレッションテストは、このリグレッションが発生していないか確認するテストです。このリグレッションテストは通常、変更前後でテスト成功状態が維持されることを確認して、意図しない変化がソフトウェアに発生していないか確認するアプローチをとります。
このリグレッションテストをどう方針立てするかは、テストの方針にとって重要な課題です。
というのも、ソフトウェア開発では仕様や設計の変更がありふれていますし、デバッグによる変更がリリース間際まで続きます。そこでは一般的に変更の度にテストを全てやり直すほどの期間やリソースがないため、絞り込んだ限定的なテストケースでリグレッションテストを構成せざるを得ません。このテストの絞り込みは変更内容によって大きく変わるため、その場その場で、プログラマやテストエンジニアが判断することになります。
そこで事前のリグレッションテストの方針立てが重要になります。適切な方針を提示できていると、その場その場のリグレッションテストを適切な方向に誘導できます。逆に方針立てがないと、好き勝手な判断で、不適切なリグレッションテストが行われる可能性を高めます。
リグレッションテストの方針立ての難しさ
ただ重要であっても、リグレッションテストの方針立ては次のような難しさから、具体化しにくい事情もあります。
- リソースや期間が不足するのが当たり前
リリース間際でテストの期間・工数が確保できない状況下でもデバッグで変更され続ける状況がありふれている。また仕様変更は全テストのやり直しを考慮してまで行われるのは稀である。そのため、本来必要なリソース・期間が確保できない状況が珍しくない。 - リグレッションリスクの十分な識別は困難
ソフトウェアの影響範囲は、直接的な結合のほか、DBや実行環境、ブラックボックスのフレームワーク等を介して広く波及する。影響の程度も、非同期処理などではテスト条件が膨大で全容把握が困難。変更の影響範囲をそもそも正確に特定できない。
このように不十分なリソースで、特定困難なリスクに対応するため、そもそもリグレッションテストは、テストチームのテストだけでは対応不能な場面も少なくありません。
なお、重要であることからテスト計画に関わる標準やプロセス、テンプレートの多くは、リグレッションテストの方針立てを計画段階で要求しています。ただこの難しさから、適切な方針立てをあきらめ、以下のような記述で形骸化させてしまう場面を複数見ます。
- 現場と乖離して実現困難な方針を立てる。極端な例では、全ての再実施を要求するなど
- 空虚で実質的に何も影響を及ぼさない方針をたてる。「影響範囲をテストする」の一文で済ませるなど
こうした形骸化を防ぐためには、前述のリグレッションテストの難しさに向き合う必要があります。
リグレッションリスクは様々な手段で対応する
リグレッションテストの本来の目的は、リグレッションリスクのコントロールです。具体的にいうと、テストでリグレッションリスクの顕在化を確認し、許容できない品質リスクがあればデバッグを通してリスクをリリースできるレベルまでコントロールすることを目指します。
この「リグレッションリスクのコントロール」ですが、当然手段は手動のテストだけではありません。他の特に有効な手段として次のようなものがあります:
開発者による変更レビュー
例えば、DRBFMなど変更に対する設計レビュー、PRレビューといったコードレビューです。
これら開発チーム内のレビューは、あからさまな開発ミスによるリグレッションの流出防止に有効です。
注意として、変更範囲が大きいと人間のレビューでは影響範囲が追いきれなくなるため、細かい粒度で習慣的にレビューを実施するのが重要です。
自動化されたリグレッションテスト
自動テストは再実行が容易なため、絞り込みすることなく、変更ごとにフル実施しやすいメリットがあります。そのため、リグレッションの網羅的な確認を効率よく安定してこなせます。一般的に、リグレッションテストの主力となる手段です。
注意として、手動のリグレッションテストは全て自動化することはできません。自動テストでは探索的テストの強み(微妙な品質の異常の確認や、探索的な意地悪な操作の試行など)を再現しにくいデメリットがあります。
そのためリグレッションテストを自動テストのみで済ませられない場面も多く、その際は手動のテストによる補完が必要になります。
Cover & Modify
これは、開発者判断で、リグレッションが発生しそうな箇所に自動テストを書き、変更前後でそのテストが合格状態であることを確認するプログラミングアプローチです。前項の自動リグレッションテストの応用例の一つです。
このアプローチでは、開発者が怪しいと思う箇所(不吉な臭い)にリグレッションテストが配備されるため、開発者の知見や思考を活用してリグレッションリスクを軽減できます
リグレッションリスクを局所化する設計の工夫
ソフトウェアの変更性を高める設計の工夫です。具体的には、コンポーネント間の結合度を下げる工夫を実施し、変更する際の影響範囲やリグレッションリスクを局所化する対策を推進します。
例えば、金銭や個人情報を扱うといったハイリスク機能は、特定コンポーネントにアーキテクチャ設計的に隔離してトラストバウンダリを設けて、それ以外の変更時のリグレッションリスクを軽減するといったアプローチが典型例になります。
反面教師として、変更性の悪い設計(全体が複雑に結合し、変更影響を限定できない設計)の場合、変更の際のリグレッションリスクが極大化して、何が起こるかわからなくなります。そうした場合では、リグレッションテストの絞り込みが困難になります。
リグレッションテストの方針
リグレッションテストの基本方針は、上記の有効な手段で十分にリグレッションリスクを軽減したうえで実施する、という形になります。これによりリグレッションテストに必要なリソースや期間を、実現可能なレベルまで軽減します。
この基本方針に基づくリグレッションテストの作り方のアプローチは次のようになります:
- 設計、コードを見て(変更性を高め、コンポーネント間の結合度を下げるアーキテクチャバウンダリを確認して)、リグレッションリスクの確認範囲を絞り込む
- 変更レビューなど変更アプローチと、開発者テスト、自動テストを見て、自分たちのリグレッションテストまでに残留しているリグレッションリスクを評価する
- 残ったリグレッションリスクに基づいて、テストケースを絞り込み実行する。
以降のリグレッションテストは、基本的にリスクベーステストになります。変更をレビューし、そこから想定されるリグレッションリスクを識別して、対応が必要なものにかかわるテストをピックアップします。
リグレッションテストの方針は、上記のようなアプローチを具体化して定義するのが、妥当なものの一つになります。