いまどきの開発ワークフローに静的解析を組み込む方法

昨今の解析ツールに対する期待

私たちのお客様のところでよく見うけられるのが、Gitベースの開発環境に動的なブランチとマージというやり方です。チームは、この種のワークフローに静的解析をシームレスに統合できることを期待しています。

大規模で複雑なコードを開発するチームは、静的解析ツールに対して以下を期待しています。

  • CI/CDプラクティスと緊密に統合できること
  • 日々の作業に役立ち、長く待たせることなく、すばやくフィードバックを返すこと
  • 既存の問題をフィルターし、フィーチャーブランチに関係する新しい違反だけを表示すること
  • 抑制/免除を効果的に共有・管理できること

最新版の2020.2では、Parasoft C/C++test を最近のワークフローにいっそう適したものにする拡張がいくつも導入されました。この記事では、なかでも注目すべき新機能をいくつか紹介します。

  • フィードバックを加速する静的解析スコープの自動適用
  • 当面の問題への集中による生産性向上
  • よりすばやい問題の修正を可能にするCI/CDの静的解析結果への容易なアクセス
  • 抑制の共有を容易にする抑制管理機能

フィードバックを加速する静的解析スコープの自動適用

静的解析セッションは、特にコードの規模が大きい場合、時間がかかることがあります。機能に小さな追加を行ったり、バグを修正したりする開発者にとって、これは問題です。開発者たちは、変更した最新のファイルに対するフィードバックをすばやく受け取り、何もかもが記憶に新しいうちにコードを修正したいと考えています。この段階では、解析の正確さよりもスピードが重視されます。

Parasoft C/C++test 2020.2ではGitとの統合が拡張されました。解析のスコープを自動的に調整し、最近行われたコードの変更だけに集中できるようになりました。

開発者は、現在の開発ブランチと比較する対象の親/参照ブランチを指定できます。Parasoft C/C++testは自動的に比較を行い、解析対象の差分を算出します。

図 1: 親ブランチと現在の開発ブランチの比較

解析に何時間もかかることもあるプロジェクト全体ではなく、ツールが自動選択した最小限のファイルのセットだけを解析します。すると、解析セッションの時間が劇的に短縮される可能性があります。

当然ながら、システムレベルでプロジェクトを検査する必要がある一部のルールの結果は、100%正確ではありません。高速な限定的実行と、広範囲で徹底したCI/CDスキャンを組み合わせることを推奨します。

最小限のファイルセットに対する静的解析の実行

この機能を有効にするには、2つのオプションを設定する必要があります。下の画面ショットは、C/C++testで使用する「ローカル設定」ファイルの例です。CUIを利用する場合、cpptestcliの -localsettingsコマンドラインフラグで指定します。

図 2: ローカル設定ファイル

scope.scontrol.files.filter.modeは、ブランチの比較を基に解析スコープを計算するか、またはローカルで変更されたファイルを基にするかを指定します。2つのブランチを比較し、変更されたファイルだけを解析するには、scope.scontrol.ref.branchオプションを使用して参照ブランチを指定します。

GUIにおいても、同じローカル設定ファイルを使用してこの機能を設定できます。ローカル設定ファイルは、Parasoft メニューの [設定] > [Parasoft] > [C/C++test 詳細設定] > [設定ファイル] で追加します。

この新機能により解析セッションの時間が短くなり、変更されたファイルだけに解析を集中することで開発者の生産性が向上します。それでも、開発者はさらに静的解析を絞り込みたいと考えるかもしれません。詳しくはこの先をお読みください。

当面の問題への集中による生産性向上

コンプライアンスを考慮せずに開発されたコードを改修しなければならないことは珍しくありません。たとえば、標準に準拠していないレガシーコードや、コンプライアンスを考えずに開発されたプロトタイプなどです。この種の状況でコーディング標準を適用しようとすると、まさに悪夢になりかねません。

いつかはコードをきれいにしなければならないのは分かっています。しかし、それは当面の目標ではありません。まず、新しい問題を持ち込んでコンプライアンス上の負債を増やしていないことを確認するのが先です。

問題は、新しい違反と既存の違反を見分けるのには非常に時間がかかるという点です。Gitと統合し、解析スコープを限定していても、新しいコードを追加しようとファイルに手を加えたとたん、ファイルに元からあった違反もすべてレポートに表示されるようになります。こうした問題を確認するのには時間がかかります。

このような困難な状況を改善するのが、静的解析結果のベースライン化です。C/C++test 2020.2には、解析セッションの実行時に、受け入れ済みの状態を表す参照レポートを指定するオプションがあります。

参照レポートは解析セッションの全結果と比較されます。既存の指摘事項をフィルターし、新しい問題だけをレポートします。

図 3: 参照レポートの結果+現在の結果=新しい結果

開発者にとっては、何百もの違反を確認する代わりに、コード変更後に現れた3つの違反だけに集中すればよいことを意味します。

結果のベースライン化を有効にする

結果のベースライン化を有効にするには、まず、参照レポートを生成します。

  1. 参照ステータスのコードに対して静的解析を実行し、参照レポートを生成します。レポートを生成するには、C/C++testの詳細設定ファイルで追加のオプションを指定します: Parasoft メニューの [設定] > [Parasoft] > [C/C++test 詳細設定] > [設定ファイル]

    図 4: 参照レポートの生成
  2. 参照レポートを SCM に保存するか、ローカル ドライブに置いて使用します。
  3. 新しい結果だけを参照するには、詳細設定ファイルに2つのオプションを追加で指定し、現在のブランチに対して解析を実行します。Parasoft メニューの [設定] > [Parasoft] > [C/C++test 詳細設定] > [設定ファイル]

    図 5: 以前のリリースのレポートをベースラインとして使用する

ローカル設定ファイルの例でreport.xmlを指定している箇所には、すべて相対パスまたは絶対パスも含めることができます。

よりすばやい問題の修正を可能にするCI/CDの静的解析結果への容易なアクセス

Git との統合と、解析スコープを制限することでフィードバックを加速するという話のところで、スキャンを制限したら、CI/CDによる広範囲の徹底したスキャンで補完すべきであると説明しました。

CI/CDの結果へのアクセス

このアプローチでは、重要な課題が1つ発生します。どうやってCI/CDの結果を開発者が参照し、アクションを起こして修正できるようにするかという問題です。結果を提供する方法はいくつかあります。

  • CI/CDプラットフォームのWebインターフェイス
  • Parasoft DTP レポートサーバーで共有する
  • 開発者のIDEに直接配布する

大多数のチームは3つ目のオプションを選びます。なぜなら、一番よく使うインターフェイス、つまりIDEから結果にアクセスできるからです。

静的解析結果へのアクセス

最新のリリースでは、Visual Studio Code拡張機能の強化も行われ、DTPから静的解析の結果をダウンロードできるようになりました。この機能は、EclipseおよびVisual Studioでは以前から提供されていたものです。

結果のダウンロードは簡単です。Command Paletteから次の専用コマンドを呼び出すだけです: C/C++test: Load Results from DTP …

図 6: 結果のダウンロード操作

DTPサーバーの場所、認証情報、DTPプロジェクトおよびフィルターの指定が求められます。

するとどうでしょう!ダウンロードされた結果が、ローカルで生成された結果と同じように [Problems] ビューに表示されます。

違反のメッセージはクリック可能です。クリックすると、修正が必要な行に直接移動できます。驚くほど効率的です。

抑制の共有を容易にする抑制管理機能

本気で静的解析を統合しようとするチームは、抑制または免除を効果的に管理する方法が成功に重要だと理解しています。Parasoft製品のユーザーは、コードのコメントという形で抑制情報を直接ソースコードに保存するか、Parasoft DTPまたはTCMのような外部データベースを使うことができます。

おそらく、抑制情報をコードのコメントという形で保存するのが最も効果的に例外を管理する方法です。しかし、別のツールを使っているかもしれない外部委託者にコードをデリバリーする場合など、この方法が使えないチームも多いでしょう。あるいは、内部的なポリシーでこの方法が禁じられているかもしれません。

新しく、コードファイルを編集することなく違反を抑制する3つ目の抑制方法が導入されました。この方法は、抑制情報でソースファイルを汚すのを避けられます。

プレーンテキスト形式で抑制を保存する

この新しい抑制方法では、抑制をプレーンテキストファイルに保存できます。ソースコードのフォルダーごとに1つの抑制ファイルを使用します。抑制ファイルはparasoft.suppressという標準化された名前を持ちます。リリース2020.2から、すべてのParasoft静的解析ツールが解析時にparasoft.suppressファイルを取り込むよう事前設定されています。この機能を使用するのに追加の設定は必要ありません。

ユーザーは、専用のUIアクションを使用するか、または手動でエントリを追加することで、parasoft.suppressに新しい抑制エントリを追加できます。Eclipseプラグイン、Visual Studioプラグイン、Visual Studio Code拡張機能のUIは、新しい抑制タイプをサポートするよう拡張されています。

抑制エントリは単なるプレーンテキストであり、抑制対象の違反を識別するさまざまな属性が含まれています。次の画面ショットは抑制エントリの例と抑制エントリでサポートされるすべての属性のリストです。

図 7: 抑制エントリ

メッセージ属性には基本的な正規表現(‘*’, ‘?’)を使用できるので、1つの抑制エントリで複数の違反を抑制できます。たとえば、メッセージにパラメーター名が含まれている場合などにも対処できます。

必要であれば、1つの抑制エントリで複数の違反を抑制できます。しかし、抑制された個々の違反の情報は、生成されたレポートにも記載されます。また、そのように設定すれば、DTPサーバーにも反映されます。

図 8: マージ

抑制ファイル(parasoft.suppress)はSCMに保存するよう想定されています。ブランチを作成すると、抑制情報もブランチの一部になります。抑制ファイルに新しいエントリを追加すると、コードレビュープロセスでそれがわかるので、抑制ファイルも一連の承認を受けます。コードをマージすると、抑制ファイルもソースコードと同じようにマージ操作に含まれます。単純明快です。

まとめ

最近の開発フローはGit SCMをベースとして標準化され、CI/CDを重視します。コードの規模が大きいこと、またブランチが高い頻度で行われることから、自動的に対象を制限し、開発者の現在の作業に関連した結果を生成する静的解析ツールを採用することが必要になります。

プロジェクトではしばしばオープンソース、レガシー、プロトタイプのコードを扱うため、コーディング標準へのコンプライアンスを達成するには、チーム独自のペースを定め、独自の計画を立てる必要があります。結果のベースライン化は、新しいコードには厳しいポリシーを確立し、既存の問題に対処する計画をすばやく効率的に立てるのに役立ちます。

(この記事は、開発元Parasoft社 Blog 「Integrating Static Analysis Into Modern Development Workflows」2020年12月10日の翻訳記事です。)

Top