ソフトウェアプロダクトライン開発でのテストアプローチ

ソフトウェアプロダクトライン開発とは

ソフトウェアプロダクトライン開発(SPLE:Software Product Line Engineering。ソフトウェア製品系列開発)は、複数の類似した製品群(プロダクトライン)の開発についての開発手法・テクニックです。プロダクトラインで共有する資産を効果的に運用して、プロダクトラインの価値を高めたり、開発生産性を高めたりすることを目指します。

ここでいうプロダクトラインは次のようなものです。

  • 仕向け地ごとといった複数のバリエーションのグループ
  • 異なるグレード群のグループ

SPLEは、複数の製品で共有する共通資産をソフトウェアプラットフォームとして開発し、それを使って個別のソフトウェアプロダクトの開発の効率化を目指します。

ここでいうソフトウェアプラットフォームは、コンポーネントといったソフトウェアの部品だけでなく、その要件、設計、テストといった開発情報も含まれます。

このソフトウェアプラットフォームを整備し、複数のプロダクト群に共通資産として展開することで、次の恩恵を確保します。

  • 開発リードタイムの短縮。既存の共通資産を活用することで個別プロダクトの開発リードタイムを圧縮する。
  • 開発費用の低減。既存の共通資産を活用することで、複数のプロダクト群を開発する場合の総コストを削減する。
  • 品質の向上。品質を作りこんだ共通資産を活用することで、その作りこみの恩恵を個別プロダクトでも享受する。
  • 顧客価値の向上。上記のリードタイム短縮やコスト削減、品質向上の帰結として、顧客価値を向上する。

また上記以外の副次的な恩恵として、製品群の保守のサポートや、アーキテクチャの複雑化対応といったものも実現します。

ソフトウェアプロダクトライン開発のプロセス

SPLEは、ソフトウェアプラットフォームを開発するドメイン開発プロセスと、個別プロダクトを開発するアプリケーション開発プロセスの二つのプロセスを独立で運用します。

ドメイン開発プロセスでは、プロダクトマネジメントの活動で、プロダクトライン(製品系列)のマーケティング、企画、ポートフォリオ管理を行います。プロダクトマネジメントは、プロダクトラインの製品ロードマップをドメイン開発プロセスに対し出力します。SPLEの製品ロードマップは、将来にわたってのプロダクトラインの共通フィーチャ、可変フィーチャの要件の情報を含みます。
そしてプロダクトマネジメントの結果に従って、ドメインの要求開発、設計、実現(Realisation。詳細設計と実装)、テストをインクリメンタル・反復的に実施して、ソフトウェアプラットフォームを蓄積・整備していきます。

アプリケーション開発プロセスでは、通常のプロダクト開発を行います。要求開発では、ドメイン要求とアプリケーション要求を両方分析し、ソフトウェアプラットフォームの活用が増えるように要件定義を行います。以後の設計、実現、テストについても、ソフトウェアプラットフォームの資産を活用して、開発生産性を高めていきます。

ソフトウェアプロダクトライン開発を支えるテストアプローチ

SPLEにおいてソフトウェアテストは重要な役割を果たします。
特にソフトウェアプラットフォームに対するテストは、次の二方面から開発生産性を支えます。

  • プラットフォームの品質確保を支え、それによってプロダクトラン全体の生産性向上を支える。
  • 資産として共有されることで、アプリケーションに対するテストを効率化する。

一方で、SPLEのような共通資産を活用するアプローチでは、可変性の管理、可変性への備え、共通資産と個別プロダクトの連携といった、様々なテストアプローチの工夫が求められます。
以降に、SPLEに求められるテストアプローチを解説します。

全体最適が得られるようにドメインテストとアプリケーションテストを分担させる

ドメインテストとアプリケーションテストの分担の適切さは、プロダクトライン全体の生産性に影響します。

特に定番の課題となるのが、プラットフォームに対し、ドメインテストをどの程度詳細に実施するかです。

まずドメインテストは簡易的な確認しかせず、必要なテストの責務をアプリケーションテストのみで対象仕様とすると、個々のプロダクトごとに大きなテスト期間・リソースが必要になり、プロダクトライン全体での効率化を悪化させます。

逆にドメインテストで詳細なテストをして、そのプラットフォーム部分のテストをアプリケーションテストでは省略するアプローチでは、次のような要因でコストが過剰にかかることになります。

  • ドメインテストで多種多様な変異体のテストをしなくてはならない。
  • アプリケーションの実行環境や依存コンポーネントが存在しない状態でテストしなければならない場面が増える。Test Doubleで代替できることもあるが、SPLEがフィットする大規模な組込み製品といったタイプでは現実的でないことが多い。

上記のような制約があることから、ドメインテストとアプリケーションテストは、無理なく共有資産化の効果を得られる分担のバランス取りが求められます。具体的には次のような方針で分担する必要があります。

  • ドメインテストは次の方針に従う。
    • コードレベルのテスト(例えばユニットテスト)は網羅的に作成する。
    • 共通部分に対しテストを作成する。プロダクトごとの可変部分については、テストがやりやすいように、再利用可能なテスト資産をアプリケーション開発に対して提供する。
  • アプリケーションテストは、資産として提供されたドメインテストを再利用する形で、アプリケーション固有のテストを作成する。

ドメインテストは段階的に育て洗練させる

前述で少し触れましたが、ドメインテストは、アプリケーションの実行環境や依存コンポーネントが存在しない状態でテストしなければならない場合があります。これは複雑な製品ではTest Doubleによる対応が難しい制約があります。
この制約に対応するため、ドメインテストは次のような段階的な洗練を行う必要があります。

  • 【最初のアプリケーション開発初期】ユニットテストや、小中規模の仮想環境でのテストといった、限定的なテストを実施する。
  • 【最初のアプリケーション開発中記】アプリケーションのプロトタイピング環境を流用し、それを使って共通部分に対するテストを充実させる
  • 【最初のアプリケーション開発後期、次のアプリケーション開発開始期】最初のアプリケーションの環境をベースに、テストを充実させる。

テストをプロダクトコードのパラダイムに合わせる

SPLEのプラットフォームは共通化の促進のため、特別なパラダイムを適用する場合があります。この適用は、プラットフォーム全体に適用することもあれば、プラットフォームとアプリケーションの境界レイヤに限定して提供する場合もあります。
適用されるパラダイムを以下に示します。

  • ジェネレーティブなコード。コード生成ツールやモデル駆動開発ツールを使って、アプリケーションに合わせたコードを自動生成する。
  • メタプログラミング。高位ロジックでアプリケーションに合わせたコードを実現する。
  • プリプロセス。プリプロセッサ処理でアプリケーションにあわせたコードを実現する。

プラットフォームのテストは、プラットフォームのコンポーネント資産とセットで利用されるため、そのテストは、プラットフォームと同じパラダイムに遵守するのが基本です。

例えば様々なアプリケーションに柔軟に対応するため、プラットフォームの資産をジェネレーティブにすることは珍しくありません。その際は、テストもジェネレーティブにしなければなりません。すなわち、プラットフォームを生成できるようなパラメータ設定を、テストにも適用できるようにする必要があります。

可変性はプロダクトマネジメントの管理下に置く。テスト単独で対処しない

SPLEは、可変性をプロダクトマネジメントの管理下に置く必要があります。具体的には、プロダクトライン全体の視座でフィーチャや可変性を把握し、それに基づいてプラットフォームの可変性を開発する必要があります。
これは、際限のない無数の選択肢・バリエーションを、費用対効果に見合う可変性スコープに絞り込むためです。

テストでは、品質リスクに基づいてテストを作ることから、プロダクトマネジメントのスコープ外の可変性をテスト使用する場面が出てきますが、これは不吉な兆候です。

もしスコープ外のテストを作らなければならない理由が、プロダクトマネジメントの不備ならば、プロダクトマネジメントを立て直して、ドメインの要件分析、開発、テストと一通りのドメイン開発プロセスをまわすのが妥当です。プロダクトマネジメントの不備をテストでごまかすと、プロダクトライン開発全体に悪影響を及ぼすリスクを高めます。

一方、プロダクトマネジメントが適切なのに、スコープ外のテストを作ろうとする場合も問題を起こします。その場合、根拠が不明なテストが生まれ、アプリケーション開発を阻害するためです。

なおスコープが曖昧になりがちなポイントに、時間軸の可変性があります。これは、将来追加される可能性のある可変性です。ただこういったものも、基本的にプロダクトマネジメントの管理下におくべきものになります。

自動化されたリグレッションテストおよびテスト自動化容易性を充実させる

ドメイン開発でもアプリケーション開発でも、ユニットテスト結合テストにて、自動化されたリグレッションテストを満遍なくコンポーネントに配備することが重要です。
というのも、SPLDではドメイン開発プロセスとアプリケーション開発プロセスが独立で動くことで、変更の割り込みがよく発生するためです。例えばプロダクトラインの複数のプロダクトを並行開発しているときに、あるプロダクトでプラットフォームのバグが見つかり、プラットフォームのデバッグと、プラットフォームを共有している他のアプリケーションへのデバッグの取り込みが発生する、といったことは珍しくありません。プロセスが独立で動いていることから、この変更の割り込みはリリース間際でテストが十分に行えないタイミングで発生することもあります。

そこで重要になるのが、自動化されたリグレッションテストをプラットフォームにもプロダクトにもいき渡しておくことです。そのテストがあると、変更の割り込みの受け入れが容易になります。

また、自動化されたリグレッションテストをいきわたらせるために、テスト自動化容易性をいきわたらせるのも重要です。それにより、プラットフォーム側から十分なリグレッションテストを提供できなくとも、アプリケーション開発の中でリグレッションテストを構築できるようになります。

テストのモジュール性とトレーサビリティを確保する

テストの再利用を容易にするためには、テストのモジュール性の改善が必要です。保守がしやすいよう責務割り当てが適切で、外部に不必要な依存性を持たないモジュール性設計をテストコードでも推進することで、プラットフォームのテストを共有するのも、アプリケーションのテストをプラットフォームに取り込むのも容易になります。

また、テストのインプットとなっている要件や設計とのトレーサビリティの明確化も重要です。可変性設計、変異性設計ではフィーチャを単位としますが、フィーチャごとにテストを紐づけることで、フィーチャの取捨選択においてどのテストを選出すればよいか明確になります。

持続可能なテストウェアやテストシステムを利用する

SPLEのプラットフォーム資産は、持続可能な状態にして長く共有できると費用対効果が高まります。そのためプラットフォーム資産を構成するテストウェアやテストシステムを構築するのが重要です。

例えばSPLEのような共通資産化戦略で良く問題になるのが、依存しているプラットフォームやフレームワークの転換です。使用しているフレームワークが廃れ別のフレームワークに主流が入れ替わるというのような状況はフロントエンドを中心に珍しくなく、それによりフレームワークに依存する資産がまとめて陳腐化する、といった状況は複数見てきました。資産化戦略では、枯れて安定した技術スタックを選ぶべきなのと、変化が起きるの当たり前として資産化戦略を組む必要があります。

また本質的にSPLEと紐づいた要素ではありませんが、SPLEで使用するツールの維持コスト・ライセンスコストで悩まされる現場も見てきました。例えばSPLEのプラットフォームにモデル駆動開発を導入している場面で、そのモデル駆動開発ツールのライセンス料が高額かつロックインが協力なため、時がたつほどSPLEの費用対効果が目減りしていく状況に遭遇したことがあります。SPLEでは、長いライフサイクルで費用対効果を評価し、技術スタックを構築すべきです。

アプリケーションごとのテストの集積でなく、プロダクトラインに対する包括的なテストを設計する

SPLEでのテスト設計アプローチに、アプリケーションごとのテストを集めて、プラットフォームのテストとするものがあります。このテスト設計アプローチは弊害が多く、保守を阻害するテストの重複が多数発生するほか、テスト対象とテストのトレーサビリティ構造がツリーでなくセミラティスとなり、トレーサビリティの維持が難しくなります。

そのため、SPLEのテスト設計アプローチは、変異性を包含するプロダクトラインに対してテスト設計するのが無難です。
なお個々のアプリーケーションでないと実現できないテスト条件(環境条件など)が発生するのは少なくありません。その際は、プロダクトラインに対する包括的なテストを、チャンピオン的なアプリケーションに対するテストで実現しつつ、そこでカバーできない個々のテスト条件を、それぞれのアプリケーション条件でテストすべきです。

保守性が高まるように内部可変性を設計する

SPLEでは外部可変性の設計が解説されることが多いのですが、内部可変性の設計も重要です。特にプロダクトコードについてはテスト容易性が高まるように内部可変性設計を行い、テストコードではテストの保守が容易になるように内部可変性設計を行うのが重要です。

共通資産固有のテスト観点を使う

SPLEのプラットフォームに対するテストでは、共有資産なりのテスト観点が求められます。
具体的には次のようなものを追加のテスト観点として分析する必要があります。

  • プラットフォーム資産とアプリケーションを紐づけるアダプターやジェネレータのテスト
    • 例えばプラットフォーム資産をジェネレーティブ人するならば、ジェネレータのテストをよく考える必要があります
  • 可変性制約に対するテスト。
    • 選択しないフィーチャ、選択できないフィーチャが存在しないことのテストや、可変性制約を実現不能にする仕組みのテストが求められます。

テスト設計コンテストU-30クラス審査委員長業の振り返り

社外のコミュニティ活動として、2017年からテスト設計コンテストU-30クラスの創設とその審査員長を続けていたのですが、立候補あり今年度から大段さんに引き継ぐことになりました。良いタイミングなので、今回振り返りながら、自分の審査委員活動の総括をできればと考えています。

テスト設計コンテストとは

テスト設計コンテスト(テスコン)は、文字通りテスト設計の良否を競うコンテストです。

https://www.aster.or.jp/business/contest.html

テスコンは、指定の仕様書に対してテスト設計を行い、それを審査基準に従って点数化して順位を競います。(1回だけ中止がありましたが)2011年から毎年開催してきました。現在はNPOソフトウェアテスト技術振興協会の活動として、有志の運営委員、実行委員の手で運営されています。

自分がファウンダー&審査委員長をやっていたのは、このコンテストの一部として、途中から派生したテスト設計コンテストU-30クラスという部門です。こちらも形式は派生元(U-30クラスと区別するために、Openクラスと呼ぶようになりました)と大まかに同じですが、30歳以下という年齢制限を追加で加えています。
以下、このU-30クラスのコンテストについての自分の審査委員長としての活動を時系列で振り返っていきます。

U-30クラス創設のきっかけ

U-30クラスの創設は、テスコンをはじめ、ソフトウェアテストのコミュニティを下支えしていた吉澤さんから声をかけられたのがきっかけでした。
そこで求められたのが、主にテスコンの参入障壁を下げて、若手や初学者にもテスト技術の啓蒙やテスト設計の楽しさを広げたい、という要求です。

というのも、当時のテスコンは成果物の品質と規模が急激に高まり、参入障壁が一気に上がっていった時期でした。
その背景としては、何回かの開催を通してテスト設計方法論を使いこなすチームが増え、成果物の品質が一気に上がっていった要因がありました。またテスコンの人気により、予選として各地域で絞り込みをしないと本戦の審査ができないほどチームが増え、競争率が高まっていた背景もありました。

この傾向はテスト技術の普及・発展の点で良い事なのですが、反面、テストの初学者や若手が安易に参加しにくい参入障壁が生まれていました。そこで年齢を若手に限定するクラスを設けることで、若手や駆け出しにもテスコンに参加いただき、テスコンによるテスト技術の普及・発展を促進しようという話が生まれました。

U-30クラス審査委員チームの構築

創設にあたっては、まず審査委員チームの構築に着手しました。
そこでは審査委員を、当時のテストコミュニティで精力的に活動していた方の中から、テスト設計コンテストの出場経験のある方、高いテスト設計技術を持った方を選び、個人的にお声がけしていきました。当時の自分はWACATEというテスト技術の勉強会合宿を中心にテストの人脈を広げていた影響で、結果的にWACATE関係者がチームの主体となりました(WACATEは若手の成長を意識したイベントのため、その関係者が母体となったことにより、後述する教育特化志向につながりました)。
そこに他の方がお声がけして推薦いただいた蛭田さんを加え、テスト設計コンテストU-30クラスの審査委員チームが完成しました。

初年度のコンテスト活動の開催

U-30クラスの始動にあたっては、思いや理念あるNPO活動ということで、ミッションやビジョンを審査委員間で共有して、それに沿ってU-30クラスを形作っていこうと考えました。

具体的には、審査委員メンバーで、創設のきっかけとなったテスコンの実行委員・審査委員の想いを具体化しながら、次の目的を設定しました。

  • テスコンに若い人を参加しやすくする/テスコンのすそ野を広げる
  • テスト設計の大切さに気付いてもらう
  • テスト設計の面白さ、他人のテスト設計と比較する面白さを体験してもらう
  • 本人の次のステップアップに役立てる/新人・中堅社員教育を支援する/仲間を増やす
  • 新しいテスト設計(観点・技法・方法論)を開発する



次にコンテストの建付けを具体化してきました。
初年度は、参加者の方々に本家のテスコン:Openクラスのこれまでの蓄積(チュートリアル資料、参加チームの成果物等々)を参考にして学んでいただこうという考えで、審査基準やルールはOpenクラスをそのまま踏襲しました。またテストベースについても、スタンドアロンの組み込み製品で規模が小さい、Openクラスで何年も使われていて資産が蓄積しているという理由で、SESSAMEの話題沸騰ポットを採用させていただきました。
一方、それとは別に、初学者でも方向性が考えやすくなるように、テストの計画・アプローチにある程度の制約を指定する、U30専用の補足要求書を新設しました。

最初の開催後

初開催では、学生や新入社員といった初学者・入門者に複数参加いただき、テスコンの参加障壁を下げようという目標は一定レベルで達成できたと感じています。

ただ反省点として、コンテストの競争を重視しすぎて、目的としていた教育方面の貢献が弱くなっていました。
例えばフィードバックについては、客観的な問題点の指摘が中心であり、スキルアップにつながる改善提案や今後の動機づけができていませんでした。特に点数の低いチームについては、問題指摘が沢山羅列されるだけのフィードバックを返してしまう形になり、テスト設計初心者のためという目的とは逆行して、委縮させてしまう恐れも出ていました。

U30はミッションを持つクラスということもあり、振り返りと問題改善に当初から注力していたのですが、そこで上記問題を細かく把握・評価し、次年度への改善につなげるようにしました。

二年目以降:教育的側面を志向する

初期の反省を踏まえて、U30クラスのテスコンは、コンテストの競争よりも、参加者の成長やスキルアップを伸ばす、教育重視のイベントを試行するようにしました。

まず審査員全員で、目的のほか、目的達成のアプローチを具体化して共有し、活動の方向性を固めました:

  • 【2020】テスト設計コンテストU-30クラスの目的
    • テスコンに若い人を参加しやすくする/テスコンのすそ野を広げる
    • テスト設計の大切さに気付いてもらう
    • テスト設計の面白さ、他人のテスト設計と比較する面白さを体験してもらう
    • 本人の次のステップアップに役立てる/新人・中堅社員教育を支援する/仲間を増やす
  • 【2020】目的達成のアプローチ
    • 改善を促すようなポジティブなフィードバックを心がける
    • 適切に伝えつつ、傷つけないようにする
    • 参加チームに気づきを促すような、わかりやすいコメントにする

そして、前年度のふりかえりと、上記のアプローチに沿って、以下の改善を実施しました:

参加者の成長につながるようなフィードバックの充実

コンテスト参加チームには、問題点を指摘するフィードバックコメントを個別に返すようにしています。
従来は問題点や点数の根拠の羅列のみを返す形になっていました。改善後から、激励屋応援の言葉と、問題点をどう改善すればよいか・どう勉強すればよいかを、丁寧に説明するフィードバックを行うようにしました。
これにより1チーム当たり3ページ程度だったフィードバックコメントが、1チーム当たり十数ページの改善提案書となるようになりました。

コンテストの作業をより現場に寄り添わせるよう、テストベースを拡張

テスコンは工数などの制約がなく、テスト技術の優劣に特化してテスト設計を行う傾向がありました。
一方現場では様々な制約(人数、工数、コスト)へのフィットが求められ、その過程でリスクベースドテストや各種テスト効率化手段が要求されます。
U30では、このギャップを埋めるよう、工数上限やチーム体制の指定を行うようにしました。

三年目以降:さらに教育志向を強化する

毎年の開催での振り返り・問題改善を通して、U30は更に教育的側面の強化を志向するようになりました。
まず、コンテストの目的では、具体的なターゲットのイメージと、自分たちが何をしたいのかを、審査委員皆で協議し、同意を形成しました:

  • 【2021~】テスト設計コンテストU-30クラスのビジョン
    • ◼ターゲットとする参加者
      • テスト初心者(業務で触れているがテストの全体感・本質論に関われていない) ★メインターゲット
      • 純粋なテスト初心者(一年未満、学生) ★次のターゲット
      • テスト設計中堅、コミュニティ参加常連
    • ◼参加者にどうなってもらいたいか
      • テスト開発をやり切れる
      • テスト設計の大切さに気付いてもらう
      • テスト設計の面白さ、他人のテスト設計と比較する面白さを体験してもらう
      • 本人の次のステップアップに役立ててもらう
      • テスト技術を高めあう仲間を増やしてもらう
      • 学生教育、新人・中堅社員教育に役立ててもらう
      • テスト技術についての成長を実感してもらう
    • ■審査員がどうありたいか
      • テスコンに若い人を参加しやすくする / テスコンのすそ野を広げる
      • テストを分析設計から行うことを周知する/テストエンジニアに対する教育の機会を提供する
      • より良いテスト設計を考え続けるきっかけを提供する

そして、上記を達成するためのアプローチについても、審査委員全員で協議し、共通認識として同意しました:

  • 【2021~】テスト設計コンテストU-30クラスのアプローチ
    • ◼大会外のアプローチ
      • 初心者・経験の浅い人でも気軽に参加できるようにする
      • 初心者向けチュートリアルの開催
      • 初心者参加を促す宣伝
    • ◼大会内のアプローチ
      • 一通りのテスト設計作業を経験する機会を設ける
      • 具体的なお題でテストを考える機会を提供する
      • 三者からステップアップにつながるフィードバックをもらえる機会を提供する
      • 参加チームに気づきを促すような、わかりやすいコメントにする
      • フィードバックを無理なく対応できるようにする
      • フィードバックコメント、直接の対面コメント含め、ポジティブなコメントを充実させる
      • 書類審査のコメントで、適切に伝えつつ、傷つけないようにする
      • 発表/他の参加者の成果を知る機会を提供する

そしてこれらの目的とアプローチに沿って、コンテストの活動を強化していきました。

まずフィードバックコメントを返すだけではなく、審査委員と参加者が直接話し合って、対話や質疑応答で改善点やアドバイスを共有する、フィードバック会を追加で開催するようにしました。
また、フィードバックコメントについては、前年度の方針転換で量が爆発して弊害が出るようになっていたことから、上記アプローチに沿って洗練させてフィードバックするようにしました。
さらに審査基準についても、普遍的に現場で重視される「テストが目的・制約に沿っているか」「そもそもテストが妥当か」のテスト妥当点を新設し、良いテストは何か、どうテストすべきかを考えていただく仕組みを追加しました。

なお自身の仕事の繁忙期の体制面のリスクから、このころから山崎さんにも共同審査委員長に参入いただきました。

これからについて

社外活動とはいえ、自分自身としてもかなり気づき・成長の得られる貴重な五年間でした。誘っていただいた吉澤さんや、協力・支援いただいた審査員・実行委員の方々、参加者の方々、大変ありがとうございました。

なお現在のU-30クラスのテスト設計コンテストは、教育重視の目的とアプローチを定義し、一貫してそれに沿った運営・改善を継続することで、参加者の成長や教育につながるイベントとしてかなり充実してきたと感じています。
自分のスキルを伸ばしたいという若手にはぜひ参加いただきたいですし、ベテラン方がテスト設計について成長やスキルアップに課題意識を持っている若手を見つけたら、ぜひ参加を促していただけると幸いです。

リグレッションテストの方針立て

リグレッションテストの方針の重要性

ソフトウェアに変更を加えた際に、意図せず変更とは関係のない所で故障が発生したり潜在的なバグが顕在化したりしたものは、リグレッション和製英語デグレードとも)と呼称されます。
リグレッションテストは、このリグレッションが発生していないか確認するテストです。このリグレッションテストは通常、変更前後でテスト成功状態が維持されることを確認して、意図しない変化がソフトウェアに発生していないか確認するアプローチをとります。

このリグレッションテストをどう方針立てするかは、テストの方針にとって重要な課題です。

というのも、ソフトウェア開発では仕様や設計の変更がありふれていますし、デバッグによる変更がリリース間際まで続きます。そこでは一般的に変更の度にテストを全てやり直すほどの期間やリソースがないため、絞り込んだ限定的なテストケースでリグレッションテストを構成せざるを得ません。このテストの絞り込みは変更内容によって大きく変わるため、その場その場で、プログラマやテストエンジニアが判断することになります。
そこで事前のリグレッションテストの方針立てが重要になります。適切な方針を提示できていると、その場その場のリグレッションテストを適切な方向に誘導できます。逆に方針立てがないと、好き勝手な判断で、不適切なリグレッションテストが行われる可能性を高めます。

リグレッションテストの方針立ての難しさ

ただ重要であっても、リグレッションテストの方針立ては次のような難しさから、具体化しにくい事情もあります。

  • リソースや期間が不足するのが当たり前
    リリース間際でテストの期間・工数が確保できない状況下でもデバッグで変更され続ける状況がありふれている。また仕様変更は全テストのやり直しを考慮してまで行われるのは稀である。そのため、本来必要なリソース・期間が確保できない状況が珍しくない。
  • リグレッションリスクの十分な識別は困難
    ソフトウェアの影響範囲は、直接的な結合のほか、DBや実行環境、ブラックボックスフレームワーク等を介して広く波及する。影響の程度も、非同期処理などではテスト条件が膨大で全容把握が困難。変更の影響範囲をそもそも正確に特定できない。

このように不十分なリソースで、特定困難なリスクに対応するため、そもそもリグレッションテストは、テストチームのテストだけでは対応不能な場面も少なくありません。

なお、重要であることからテスト計画に関わる標準やプロセス、テンプレートの多くは、リグレッションテストの方針立てを計画段階で要求しています。ただこの難しさから、適切な方針立てをあきらめ、以下のような記述で形骸化させてしまう場面を複数見ます。

  • 現場と乖離して実現困難な方針を立てる。極端な例では、全ての再実施を要求するなど
  • 空虚で実質的に何も影響を及ぼさない方針をたてる。「影響範囲をテストする」の一文で済ませるなど

こうした形骸化を防ぐためには、前述のリグレッションテストの難しさに向き合う必要があります。

リグレッションリスクは様々な手段で対応する

リグレッションテストの本来の目的は、リグレッションリスクのコントロールです。具体的にいうと、テストでリグレッションリスクの顕在化を確認し、許容できない品質リスクがあればデバッグを通してリスクをリリースできるレベルまでコントロールすることを目指します。

この「リグレッションリスクのコントロール」ですが、当然手段は手動のテストだけではありません。他の特に有効な手段として次のようなものがあります:

開発者による変更レビュー

例えば、DRBFMなど変更に対する設計レビュー、PRレビューといったコードレビューです。
これら開発チーム内のレビューは、あからさまな開発ミスによるリグレッションの流出防止に有効です。
注意として、変更範囲が大きいと人間のレビューでは影響範囲が追いきれなくなるため、細かい粒度で習慣的にレビューを実施するのが重要です。

自動化されたリグレッションテスト

自動テストは再実行が容易なため、絞り込みすることなく、変更ごとにフル実施しやすいメリットがあります。そのため、リグレッションの網羅的な確認を効率よく安定してこなせます。一般的に、リグレッションテストの主力となる手段です。
注意として、手動のリグレッションテストは全て自動化することはできません。自動テストでは探索的テストの強み(微妙な品質の異常の確認や、探索的な意地悪な操作の試行など)を再現しにくいデメリットがあります。
そのためリグレッションテストを自動テストのみで済ませられない場面も多く、その際は手動のテストによる補完が必要になります。

Cover & Modify

これは、開発者判断で、リグレッションが発生しそうな箇所に自動テストを書き、変更前後でそのテストが合格状態であることを確認するプログラミングアプローチです。前項の自動リグレッションテストの応用例の一つです。

このアプローチでは、開発者が怪しいと思う箇所(不吉な臭い)にリグレッションテストが配備されるため、開発者の知見や思考を活用してリグレッションリスクを軽減できます

リグレッションリスクを局所化する設計の工夫

ソフトウェアの変更性を高める設計の工夫です。具体的には、コンポーネント間の結合度を下げる工夫を実施し、変更する際の影響範囲やリグレッションリスクを局所化する対策を推進します。
例えば、金銭や個人情報を扱うといったハイリスク機能は、特定コンポーネントアーキテクチャ設計的に隔離してトラストバウンダリを設けて、それ以外の変更時のリグレッションリスクを軽減するといったアプローチが典型例になります。
反面教師として、変更性の悪い設計(全体が複雑に結合し、変更影響を限定できない設計)の場合、変更の際のリグレッションリスクが極大化して、何が起こるかわからなくなります。そうした場合では、リグレッションテストの絞り込みが困難になります。

高頻度で小規模なリリース

なるべく高頻度に細かくリリース・デプロイして、一回の変更の規模を抑えるアプローチです。
リリースの粒度が大きいと、それだけ変更範囲が大きくなり、対応すべきリグレッションリスクが広く・高くなります。これではリグレッションテストの絞り込みが困難になりますし、前述した変更レビューや設計の工夫などのプラクティスも効果を発揮しにくくなります。
そのため、開発のリードタイムを高めて、リリースは高速に済ませられるように体制、プロセス、技術力を整備しておくことは、変更のリグレッションリスク軽減に寄与します。

リグレッションテストの方針

リグレッションテストの基本方針は、上記の有効な手段で十分にリグレッションリスクを軽減したうえで実施する、という形になります。これによりリグレッションテストに必要なリソースや期間を、実現可能なレベルまで軽減します。

この基本方針に基づくリグレッションテストの作り方のアプローチは次のようになります:

  1. 設計、コードを見て(変更性を高め、コンポーネント間の結合度を下げるアーキテクチャバウンダリを確認して)、リグレッションリスクの確認範囲を絞り込む
  2. 変更レビューなど変更アプローチと、開発者テスト、自動テストを見て、自分たちのリグレッションテストまでに残留しているリグレッションリスクを評価する
  3. 残ったリグレッションリスクに基づいて、テストケースを絞り込み実行する。

以降のリグレッションテストは、基本的にリスクベーステストになります。変更をレビューし、そこから想定されるリグレッションリスクを識別して、対応が必要なものにかかわるテストをピックアップします。

リグレッションテストの方針は、上記のようなアプローチを具体化して定義するのが、妥当なものの一つになります。

シフトレフトテストを支えるテスト設計についてSoftware Designに寄稿

最近、Software Design 2月号にて、シフトレフトテストの解説記事を執筆する機会をいただきました。

Software Design 2024年2月号

シフトテストレフトは、シフトレフトの一種で、「テスト対象を動かして動的にテストするタイミングをなるべく早く設けよう」というアプローチです。

対象を動かす動的なテストでは、単に「動的なふるまいを確認できる」というものに収まらない、多数の知見が得られます。例えば「企画書では魅力的だったけど、動かしてみると微妙」「数値上の開発進捗と比べて品質が全然作りこまれていない」「競合プロダクトとの競争が厳しいものになりそう」といった感覚的な知見がその一つです。
シフトレフトテストは、そうした動的なテストのフィードバックをなるべく多く、なるべく適切なタイミングで得られるように、プロセスやマネジメント、技術の工夫を行います。

ソフトウェア開発の当事者ならば広く有益な考え方ですので、手に取って一読いただけると幸いです。

品質保証部門の陳腐化。そして陳腐化した品質保証は品質を悪化させる

※品質保証のエンジニアである筆者が自省・戒めのために書いた記事になります

 品質管理(Quality Control)、品質マネジメントは国内では製造業を中心に発展し、プロダクトの競争力向上に貢献してきました。
 JTCと呼ばれる旧来からのメーカーでは、その実績・年功の蓄積に応じて、独立性を保った品質管理・品質保証部門が権威を獲得し、今でもソフトウェア開発に強い影響力を保持するようになっています。筆者は複数のメーカーを転職やコンサルで巡って来ましたが、例えば品質保証部門が承認しないとマイルストーンで開発がブロックされる、プロダクトがリリースできないといった権限を持つ体制が、今なお普遍的に見受けられます。

 この品質保証部門が権力を持ち、品質ゲートの門番として振る舞う体制は、今であっても、ある面で恩恵を提供しています。例えば次のようなものです:

  • 法規制対応、標準化対応、その他公的なガバナンス要求への対応の徹底
    • そうしたものは、力があり独立性が保たれた品質保証部門が推進するのが有効です。開発者任せにすると、開発の遅延や能力不足でガバナンスが乱れることがあるためです。
  • QMSや製造プロセスの継続的な改善、品質技術の継続的な蓄積
    • 品質保証に特化した部門を維持することで、QMSやプロセスの継続的な改善・蓄積が容易になります。特にQMSは中長期の継続的な整備と改善が重要であるため、プロジェクト型の組織では、プロジェクトと離れた旗振り部門があった方が都合が良くなります。
  • 客観的な品質情報の報告や品質改善提案
    • 開発チーム内の情報収集・課題認識は、遅延・炎上などで運用が乱れる場合があります。開発チームから独立した品質担当部門があると、開発状況に引っ張られずに客観的に品質を評価し、課題識別する運用が守りやすくなります。

 ただ、ソフトウェア開発のようなプロダクトの様相が劇的に変化している状況下では、品質保証部門が旧時代的な品質管理・品質保証を権力をもって強制し続けているせいで、ソフトウェア開発に悪影響を与えている事例が一部であります。

 典型例として、最近メーカーで多いのが、デリバリーの高速化・高頻度化対応の阻害です。
 旧来は、ソフトウェアを完成させ、しっかり品質保証してから(品質熟成の期間を長く確保してバグを取りきってから)、工場や顧客に納入したり、パッケージ化して市場展開したりする、ウォーターフォールベースの開発プロセスが少なくありませんでした。

 ただここ20年超、プロダクトの形態が、パッケージからSaaS等のサービスに変わったり、OTA等で継続的にアップデートしてプロダクトを改善し続けたりするものに変わってきています。それに伴い、開発アプローチとして、継続的デリバリやDevOpsのような、開発のリードタイム短縮、デリバリの高頻度化、ユーザの要求対応の迅速化(いわゆるDORA Four Keysがその典型です)が重要になってきました。

 しかし、品質保証部門が、その変化に対応できずに、旧来のウォーターフォールプロセスを実質的に強制するような、長大な時間・コストを要する品質保証を強制し続けて、開発アプローチの改革を困難にしてしまう事例が、JTCにて今でも見受けられます(もちろん時代の変化にうまく対応し適切なソフトウェアの品質保証を行っているところも普通にあります。今回は、長年の年功で獲得した権威から、変化をうけいれられなくなっている特に悪い例について解説します)。

品質保証部門の陳腐化は品質を棄損する

 求められる品質が大きく変わり、それに応じて開発の体制やプロセスの改革が求められているのに、権力を持った旧来の品質保証部門が改革をブロックしている状態は「品質保証部門の陳腐化」というべきものです。

 この品質保証部門の陳腐化が悪化すると、プロダクトの価値を大きく棄損します。
 まず鈍重なアプローチの強制は、開発のスピード・コストをダイレクトに悪化させ、ビジネスの機会や利益を棄損させます。
 さらにプロダクトの品質も低下させます。必要最低限の有限な開発リソース(コスト、時間、人)を、重厚長大な品質保証対応で浪費させて、本当に必要な品質の確保・保証のためのリソースを不足させてしまうためです。これは品質の向上・保証のために膨大なリソースと時間の投入を強制しているのに、逆に品質を悪化させているという、いびつな構図を生み出します。

品質保証部門の陳腐化の兆候

 この権力ある品質保証部門の陳腐化には、次のような兆候・傾向があります:

プロダクトへの価値貢献ではなく、旧来のプロセスの権威化で自分たちの存在価値を確保している

 過去の実績に基づいて構築した品質保証プロセスをトップダウンで守らせ続けることで、自分たちの影響力・権力を維持する傾向です。
 一方で「今の自分達がこれからのプロダクトへの価値貢献に貢献できているか」という責任からは逃避します。
 また、旧来の品質保証プロセスを、最新のプロダクト状況に合わせて改善することは、自分たちの能力不足を隠すために、暗に抵抗します。

 この傾向の副次的な特徴として、自分たち品質保証部門のプロセスやルールに従わないと、開発をやたら不必要にブロックする(次工程に着手させない、品質保証部門の是正要望対応にリソースを全投入させる)というのもあります。これは、現場に対して、陳腐化してなお品質保証部門の権威付けを行おうという強迫観念が顕在化したものです。

 また、プロセスの背景となる方法論や哲学への信仰もよくある特徴です。JTCでは長年の蓄積で品質管理の方法論や考え方(例えば品質会計など)を構築していることが少なくありません。
 それらが一概に悪いというわけではないのですが、陳腐化した品質保証部門は「その方法論を完璧にこなしてこそ価値を出せる。逸脱すると価値が棄損する」という盲信に近い姿勢で、企業の伝統的な方法論・プロセスから逸脱させない姿勢を徹底することがしばしばあります。

本質的な品質理解を行わなず、旧来のメトリクスの数字で品質を判断する

 ソフトウェアの品質が妥当か、本質的な判断を行わず、旧来のメトリクスの数字が基準以上かで品質判断する傾向です。
 この傾向でありがたられるメトリクスの定番としては、テストカバレッジ、テスト密度、バグ密度、レビュー密度、レビュー指摘密度などがあります。
 例えば、本質的にテスト設計が適切か判断できないため、テスト密度やバグ密度の数字が基準を満たしているかでテスト品質の判断を確定します。

 この傾向の副次的特徴として、影響力の保持のため、必要以上にメトリクス基準を厳しくすることがあります。
 例えば典型例としてテストのコードカバレッジ100%があります。コードカバレッジ100%は一部の高信頼性製品開発を除いて、難しさ・手間の大きさに対して得るものが少ない、現場に見合わない基準です。しかし陳腐化した品質保証部門は、「テストで網羅しない箇所が問題ないか判断できない能力不足」をごまかすため、一律100%義務化といったことを強制します。

プロダクトバリデーションを放棄して、プロセスバリデーションに偏重する

 能力不足により、本質的に必要な品質の確保・保証(プロダクトバリデーション)に手を出せない状態です。かわりに、旧来のプロセスルール(ドキュメントテンプレート、構成管理、レビュー量、承認プロセスなど)の遵守をもって品質保証の判断を行う傾向を強めます。

 本来プロセスバリデーションも品質保証で重要な活動です。ただ陳腐化においては、能力不足で本当に妥当なプロセスか判断ができなくなっており、旧来のプロセス定義に沿っているかでもって判断を行おうとします。

 この特徴の副次的特徴としては、テンプレート違反や内部工程の承認不備といった、本質的な価値貢献から離れた指摘の比率が大きくなる傾向があります。

 なおプロセスバリデーションによる品質評価は、工場の製造プロセスといった対象ならば有効です。ただソフトウェア開発は製造プロセスと比べて非決定的要素、属人的要素が大きいため「プロセスがしっかりしていればよい」という判断だけではリスクが残留します。

能動的な品質理解を行わず、受け身で品質を判断する

 能力不足により、自立して主体的に品質を評価できない傾向です。
 自力で評価できないリカバリとして、自分たちが品質を理解できるまでの説明責任を、開発部門に負わせます。そこでは自分たちの能力不足で理解できないものは、開発部門の説明不備に責任転化します。

 この傾向の特徴として、品質保証のエビデンスを数多く開発部門に負わせるというものがあります。開発過程で生み出されるドキュメントや、日ごろの開発部門の報告を聞いていれば本来わかる情報についても、品質保証用に説明した追加のエビデンスを要求します。
 また、品質理解を、品質保証のマイルストーンが近づいてから着手する、という特徴もよく見られます。日ごろから開発部門に入り、そこでの報告や作成資料を読んで品質情報を把握しておく、といったアクションが能力不足でとれません。

開発のリードタイム高速化による品質改善を評価しない。品質ゲートによるバグゼロ志向に傾倒する

 時間をかけて(テストやレビューを増やす等)品質を改善するアプローチしかとれないという傾向です。

 近年のDevOpsといった開発スタイルでは、DORA Four Keysに代表されるように開発のリードタイム高速化で、サービスを高品質化するアプローチが取られます。バグが見つかっても、高速に修正してユーザへの悪影響を軽減する、というアプローチです。
 注意として、このアプローチであっても、リリースにバグを残さない・市場にバグを出さないという品質保証活動が重要なのは間違いありません。高品質な開発をしつつ、開発も高速化して、バグを出さない・出してもすぐ改善するのを両立する形を目指します。
 これは、リリースして終わりではなく、継続的に運用や改善を続ける現代的なプロダクトで、常識的に目指すべき基本方針となります。
 
 しかし陳腐化した品質保証部門は、能力不足で品質保証業務を高速にこなせない制約により、仕事の高速さ・リードタイムの短さを価値におくことを避けます。品質活動の速さを評価基準にすると、自分たちの能力不足が露呈するためです。
 品質保証活動による開発遅延で実害が出たら、しばしば開発の見積もり不足・リソース計画不備に責任転嫁します。

 この傾向の副次的な特徴としては、大規模な承認会議や、鈍重なエビデンスの構成管理といった、やたら時間のかかる儀式の強制をしがちというものがあります。

ビジネスやユーザにとっての品質をリードせず、内向きの品質のみを扱う

 ユーザの要求を満たしたり、ビジネスに成功したりするのに必要な品質を見出して、その実現のために開発をリードするアプローチを取らないという傾向です。代わりに、旧来のプロセス定義との合致性や、開発部門が検出した不具合の解消といった、品質要求の変化の影響が少ない品質活動に閉じこもります。

 この傾向はどんどん変化する品質要求に、能力不足により追従できなくなった結果発生します。この傾向が悪化すると、リソースや時間をビジネスの成功に紐づかない方向で浪費することで、プロダクトの機会損失リスクを高めがちになります。

品質保証部門の陳腐化の改善アプローチ

 品質保証部門の陳腐化の主要因は、品質要求の変化で自分たちが有害なレベルまで能力不足な状態になったのに、権力を維持していることです。

 この改善には、時代にあった品質保証能力を確保し、維持し続けるのが重要になります。そのためには、次のような改善アプローチが有効です:

  • 品質保証部門の能力向上:品質保証部門で人材を閉じさせず、最新の開発能力を持つ人材、プロダクトの品質に精通したドメインスペシャリスト等を、品質保証部門に投入したり、人材を開発部門とローテーションさせたりする
  • 品質保証業務の移譲:品質リード、各種品質管理活動、インシデント管理など様々な活動がありますが、それらの能力を有する部門に移譲し、品質保証部門はそれらの全体の流れが円滑に、確実に回せるようにすることを目指す。法規制対応など自分たちが価値が発揮できる領域に直接的な品質保証の責務を絞る

PCの執筆・作業環境の整備で買ってよかったもの2023年版

今年、書籍執筆の機会をいただいているのですが、執筆期間が短く、プライベート時間にかなりの間文字を書き続けています。(体が無理できなくなったのも合わさって)そこで気になったのが、自分の自宅のPC環境の使いづらさでした。
その流れで今年後半はPC環境の整備に凝り始めたのですが、今回はそこで購入して良かったものをまとめたいと思います。

モニタ: 32インチ 4Kゲーミングモニタ(MSI Optix MPG321UR-QD)

Amazon.co.jp: MSI ゲーミングモニター 144Hz 32インチ量子ドット IPSパネル スリムベゼル 鮮やかな発色 4K UHD/1ms/HDR600対応/G-Sync Compatible/PS5対応(4K/120Hz)/HDMI2.1/DP Optix MPG321UR-QD : パソコン・周辺機器

これまでは長く27インチHDモニタを二枚並べていたのですが、評判の良さを見てその一つをこの32インチ4Kモニタに入れ替えました。

この4Kモニタは買って正解でした。執筆作業もそれ以外の作業も生産性向上を実感しています。もっと早く導入すべきだったと後悔しています。

32インチ4Kモニタの良いところは、縦方向の画素数が豊富なところです。執筆環境だけでなく、Visual Studio Codeのようなマルチビューの開発環境でも、明確な生産性向上を実感します。
執筆環境では、次のように画面を4分割して執筆しています。

またリフレッシュレート144Hzは、直接的な生産性向上効果が少ないものの、マウスやスクロールがなめらかに動いて新鮮です。作業とは別の話になりますが、アーマードコア6が高画質でぬるぬる動いて感動しました。

キーボード:REALFORCE R3(REALFORCE R3 キーボード ハイブリッド テンキーレス 30g)

Amazon | REALFORCE R3 キーボード ハイブリッド テンキーレス 30g 日本語配列 ブラック R3HC13 | REALFORCE | パソコン用キーボード 通販

キーボード愛好家の妻の勧めを聞きながら導入しました。
これまではMacBook Proでの開発に慣れていた流れでキーボードにこだわりがなく安価な普及機を使っていました。これが初の高級キーボードになります。

このREALFORCEも買って正解でした。長く文字を打ち続けた場合の指の疲労具合が明確に軽減しています。
おそらく、確かな打鍵感がありながら、打鍵が軽く反発も少ないので、指の負担が少なくなっているのではと感じています。音、感触含めて、総合的に打鍵がここちよく、タイピングが楽しくなります。高級キーボードを好む人たちの気持ちが少し分かりました。

椅子:エルゴヒューマン2 Proオットマン(EHP2-LPL-BF-BK)

Amazon.co.jp: エルゴヒューマン2(ergohuman2) オフィスチェア フレーム:ブラック メッシュ:ブラック ヘッドレスト付き オットマン内蔵 プロ オットマン EHP2-LPL-BF-BK : 文房具・オフィス用品

これまでは職場でよく見るオフィスチェアを使っていたのですが、長時間座っていると尻等が痛くなっていたほか、姿勢もよくなかったので、本格的なオフィスチェアを導入しました。

これもかなり良いと感じています。各部調整すると、椅子に合わせて座るだけで姿勢がよくなります(普通に座るだけで猫背が治りました)。良い姿勢で長時間座っても疲労感が少なく、尻が痛くなるといったことが起こりません。

一方少し気になったところとして、ヘッドレストは必要性が思ったより低いと感じました。車のシートのように常時頭を付けて安定させる使い方を想像をしていたのですが、このチェアの場合はリクライニングの時しか使わないような配置設計になっています。
またオットマンもそんなに使っていません。リモート環境ですと、オットマンを使うような状況ならば、寝具等で休めるためです。

なおレビューを見ると体格で合う合わないが多いようなので、購入する場合は試座するのがよいかもしれません。自分はIDC大塚家具の新宿ショールームで色々試し座りして選びました。

イヤホン・ヘッドフォン:Shokz OpenFit

Amazon.co.jp: Shokz OpenFit 2023年新登場 完全ワイヤレスイヤホン 8.3g超軽量 手軽なマルチポイント接続 オープンイヤー bluetooth5.2 マイク付き パワフルな低音 IP54防水性能 最大28時間利用可能 耳を塞がない 簡単操作 アプリ 日本語取り扱い説明書 ブラック : 家電&カメラ

家族がいる状態でのリモートワークではイヤホンやヘッドフォンを使うことが多いのですが、現在そこで常用しているのがこのワイヤレスイヤホンです。

これは素晴らしく手放せなくなっています。
このイヤホンはオープン型で、耳の穴を防がず、耳穴から少し離れた距離から音を発するタイプです。素晴らしいのが、とにかく装着感が軽く、装着しているのを忘れるぐらい、常時つけっぱなしでも支障がないことです。音漏れもほぼありません。また運動してもずれることがないぐらい、安定しています。
オープン型なので、自然に外音が聞けるのも良いです。イヤホンやヘッドフォンは、耳の穴や頭が痛くなったり、耳の湿気が気になったり、外音(声かけや家具の通知音など)を聞き逃したりすることが多いのですが、このOpenFitならそれらが解消します。
マイクの品質も、リモート会議をするレベルでは支障ありません。

なおShokzといえば骨伝導イヤホンが有名です。こちらも大変良いもので自分もCommとProの二台を長く使っていました。ただ振動感が強く低音を聞いているとむずむずしてくる点が気になります。OpenFitはその点も解消しています。

プロパティベーステストの概要とPythonでの実装例

 「実践プロパティベーステスト」の発売をきっかけに、国内でプロパティベーステストの話題がホットになっています。
 今回はこのプロパティベーステストの概要とテクニックについて、Pythonをサンプルに解説します。

プロパティベーステストとは

 プロパティベーステストは、「プロパティ」が成立するかを確認するテストです。ここでいうプロパティは「事前条件に対する事後条件・不変条件の関係を、実行可能にしたもの」です。

 このプロパティ、プロパティベーステストは、よく実例ベーステスト(Exampleベーステスト、事例ベーステスト)と対比して解説されることが多いため、今回もそれに習います。

 まず実例ベーステストは、テスト対象の入力と出力の実例を、テスト条件と期待値に実装するアプローチです。
 例えばソート関数を対象とする場合を考えます。実例ベーステストの場合、「リスト[2, 1, 3]を渡すと、結果としてリスト[1, 2, 3]が出力される」のように、具体的な実例値[2, 1, 3]、[1, 2, 3]を使ってテスト実装します。
 一般的なソフトウェアテストの多くは、この実例ベーステストに該当します。そこではテスト実装で入力・期待値に具体的な実例値を指定し、それに従ってテスト実行するアプローチをとります。

 一方プロパティベーステストは、入力・期待値の実装に実例を使用しません。入力を自動生成しながら「事前条件に対する事後条件・不変条件の関係」が成立するかを確認します。
 例えばソート関数を対象とするならば、「リストを入力すると、結果として昇順にソートされたリストが出力される」ことを、様々な入力を生成しながら確認します。
 なお、ここでの「結果として昇順にソートされたリストが出力される」の確認のテスト実装が難しい場合があります。その場合、「結果として先頭に入力の最小値が配置されたリストが出力される」と緩和化するような、様々な工夫を使う必要があります。この工夫は後述します。

プロパティベーステストの利点・欠点と立ち位置

 プロパティベーステストの利点に以下があります:

  • テスト詳細設計、テスト実装を自動化できる
  • 上記のメリットにより、テスト条件、テストケースを自動生成しやすい。それによりテスト条件の詳細な網羅が可能になる。
  • 上記のメリットにより、実例によるサンプリングチェックではなく、事前条件・事後条件・不変条件の仕様の実現を確認できる。

 プロパティベーステストは一方で次のような欠点があります:

  • テストオラクル問題(テストの期待値をどう確保・実装するかの問題)を抱える。それにより実例ベーステストのような詳細な期待値比較ができない場合がある。
    • 例えば「リストを入力すると、結果として昇順にソートされたリストが出力される」のプロパティを確認する場合では「結果として昇順にソートされたリストが出力される」の確認の実装が必要になる。しかしそれはプロダクトコードと重複する二重実装になってしまい、価値の低い確認になってしまうことが少なくない。その際は、プロパティの簡略化や、知恵を使った代替手段に頼る形になる。
  • 自動化前提のアプローチである。そのため自動化困難なテストでは効果を出しにくい。
  • 具体例を明示しないため、UXやユーザーストーリーといった、実物を実際に触って得られる直感的で具体的な実例が必要なテストに適用しにくい。

 このように利点・欠点双方あることから、プロパティベーステストは実例ベーステストを包括する・優れる、という関係ではありません。お互いの利点を活かしあう補完関係を取ります。

プロパティベースの具体例

 ソートメソッドsortedをテスト対象に、プロパティベーステストを実装した例を示します。このテストは、整数リストを入力で渡したら、昇順にソートされたリストが出力されることを確認するものです。

 まず実例ベーステストでの実装例を示します:

# 実例ベーステスト
def test_sort_example_based():
    assert sorted([2, 1, 3]) == [1, 2, 3]

 「[2, 1, 3]」という実例の入力をテスト対象に与えて、「[1, 2, 3]」という実例の期待値が出力と一致することを確認しています。

 次に、プロパティベーステストの実装例を示します。Pythonではファジングでよく使われるhypothesisで実装します。

# プロパティベーステスト
@given(st.lists(st.integers(), min_size=1))
def test_sort_property_based(input_list):
    result = sorted(input_list)
    assert len(result) > 0
    assert min(result) == result[0]
    assert max(result) == result[-1]

 「昇順にソートされたリストが出力される」を素直に確認できればベストなのですが、それを実装するとなるとsortedの二重実装を行うことになるため、事後条件を次のような確認で代替しています。

  • リストが空で出ないこと
  • リスト先頭が、入力の最小値であること
  • リスト末尾が、入力の最大値であること

 この代替により、実例ベーステストと比べ、プロパティベーステストは限定的なテストしかできないようになっています(先頭・末尾しか見ておらず、それ以外の要素がソートされているかは確認できていない)。その犠牲でプロパティベーステストの利点を得られるようにしています。

 プロパティベーステストでは、入力値は自動生成します。上記サンプルの場合「@given(st.lists(st.integers(), min_size=1))」で指定された「要素1個以上の整数値のリスト」をランダムに大量生成して、プロパティが成立するか確認します。

プロパティベーステストでのテストオラクル問題への対応アプローチ

 前述の通り、プロパティベーステストではテストオラクル問題が主要な課題になります。この課題への対策として色々なテクニックが考案されています。その一部を以下にまとめます。

対称性のある関係を活用する:ラウンドトリップテスト

 「エンコードしてデコードする」「シリアライズしてデシリアライズする」「保存して読みだす」のように、「処理」と「逆処理」という対象性のある機能を使います。
 その機能を使って、入力データに処理をかけ、その結果に逆処理をかけた結果が、元の入力データと一致するか確認するテストを実装します。
 このテクニックの詳細は以下を参照ください

テストオラクルに依存しないテスト実装テクニック:ラウンドトリップテスト(Roundtrip Test) - 千里霧中

推定可能な入出力の組の関係性を活用する:メタモルフィックテスト

 入出力が推定可能な関係を活用します。それにより、例えば異なる入力でも出力が同じになるようなパターンを使って、異なる入力ごとに実行した結果が一致することをもって、プロパティの成立を確認します。
 一例としてsin関数を対象とした場合を考えます。sinの入出力の関係として「sin (π − input)」と「sin (input)」は常に数学的に一致します。そこで、その関係性を利用し、同じ入力で「sin (π − input)」と「sin (input)」を実行し、それぞれの結果が一致することを確認するテストを実装します。

仕様モデルから期待値を得る:モデル駆動アプローチ

 実行可能なモデルでモデルベーステストを行う場合、モデルをテストオラクルにできる場合があります。
 その場合、プロパティベーステストで自動生成した入力値を、実行可能なモデルと、テスト対象に入力し、それぞれの結果が一致するかを確認するテストを実装できます。

プロパティベーステストと類似概念

メタモルフィックテスト

 AIシステムのテストのテクニックであるメタモルフィックテスト(メタモルフィックテスティング)は、プロパティベーステストの一種です。
 ただし、プロパティベーステストの名づけのタイミングが新しめのため、従来からメタモルフィックテストを使っている人達にとっては、プロパティベースドテストに内包されるという認識がない場合があります。
 なお、メタモルフィックテストで研究・蓄積されているテクニックは、プロパティベーステストのテストオラクル問題の改善に有益で勉強の価値があります。

QuickCheck

 HaskellのQuickCheck(QuickCheckテスト)は、プロパティベーステストと同義です。QuickCheckを広く利用できるように汎用化・普遍化したものがプロパティベーステストと言ってよいと思います。
 ただしQuickCheckの方がより古くから活用され、プロパティベーステストはそれから派生したと解釈できる余地もあるため、プロパティベーステストの呼称を避ける場合があります。

ファジング

 ファジングとプロパティベーステストの関係は、現状としてコミュニティやコンテキストに依存しています。
 伝統的なファジングは、プロパティベーステストのような詳細なプロパティの確認を行いません(システムに異常がないか、エラーが記録されていないかといった、かなりざっくりとした事後条件を確認する)。そのファジングは、プロパティベーステストとは概念が少しずれています。またプロパティベーステストはQuickCheckのようにランダムテストを許容しますが、伝統的なファジングはバグがでそうな高リスクな入力パターンを使うという違いもあります。
 一方、Go Fuzzのような一部のコミュニティや技術が呼称するファジングは、プロパティベーステストと同義です。