15
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Mavenで静的解析を実行する

Posted at

mavenのビルドで静的解析を実行して、規定のレベルに達していなければfailureを返すための設定
mvn siteで静的解析レポートを出力する例は見かけるが、testと同じようにcheckする設定例をあまり見かけなかったので書いてみた。

静的解析ツール

Jacocoは、OpenCloverとの比較検討のために追加していて、カバレッジのレポート出力(jacoco.exec)だけを実行し、カバレッジ検査は行なっていない。

pom.xmlの設定例

GitHubリポジトリ<build/><reporting/>を参照

  • 静的解析プラグインのcheckゴールを実行することでビルド時に検査する
  • 設定例では静的解析の実行フェーズをverifyとしており、mvn verify で静的解析を実行してくれる
  • レポートも出力したい場合は、mvn site を実行する。 但し後述のJenkinsのpluginでレポーティングする場合は、checkゴールを実行すれば必要なxmlファイルも出力されるので、mvn site は必要ない。

静的解析をverifyフェーズで実行している理由

これはOpenCloverのカバレッジ取得の仕組みが原因で、testフェーズ以前だと静的解析でエラーを検出してしまうため。

OpenCloverはテストカバレッジを取得するために clover:setup ゴールを実行してソースコードを改変する。この改変内容が他の静的解析でエラーで検知されることがある。
回避策としてはsetupゴールではなくinstrumentゴールで実施する。その結果、"正式なプロダクト用"と"カバレッジ取得用"の2回コンパイルが行われるので正式なプログラム用で静的解析が実行できる。 またテストも2回実行する。
但し、instrumentゴールは、2回目のコンパイルがinstallフェーズの後になってしまう。これを回避するのがinstrument-testゴールで、2回目のコンパイルをtestフェーズの後に実施するため、testフェーズより後であれば静的解析も正しくcheckする。 なのでprepare-packageゴールで実行すれば、静的解析後にパッケージングすることもできる。

つまり、OpenCloverを使わないのであれば、testフェーズで静的解析を実行しても問題ない。

Pluginの設定例

静的解析ツールを実行するためのplugin設定例をpom.xmlから抜粋した。
いずれも<build/>タグ内の設定内容。
<reporting/>タグ内には、タグ以外の設定を定義する

Checkstyle

  • checkstyle自体は8.17を指定
  • Rule Configureは、プラグインが標準で持っている google_checks.xml を定義
  • "error"の時のみfailureを出力する
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-checkstyle-plugin</artifactId>
  <version>3.0.0</version>
  <dependencies>
   <dependency>
     <groupId>com.puppycrawl.tools</groupId>
     <artifactId>checkstyle</artifactId>
     <version>8.17</version>
   </dependency>
 </dependencies>
 <configuration>
   <configLocation>google_checks.xml</configLocation>
   <failsOnError>true</failsOnError>
   <failOnViolation>true</failOnViolation>
   <violationSeverity>error</violationSeverity>
   <consoleOutput>true</consoleOutput>
 </configuration>
 <executions>
   <execution>
     <id>checkstyle</id>
     <phase>verify</phase>
       <goals>
         <goal>check</goal>
       </goals>
    </execution>
  </executions>
</plugin>

SpotBugs

  • SpotBugs自体は3.1.11を指定
  • Defaultレベルを閾値としている
<plugin>
  <groupId>com.github.spotbugs</groupId>
  <artifactId>spotbugs-maven-plugin</artifactId>
  <version>3.1.11</version>
  <dependencies>
    <dependency>
      <groupId>com.github.spotbugs</groupId>
      <artifactId>spotbugs</artifactId>
      <version>3.1.11</version>
    </dependency>
  </dependencies>
  <configuration>
    <effort>Default</effort>
    <threshold>Default</threshold>
    <failOnError>true</failOnError>
    <trace>true</trace>
    <xmlOutput>true</xmlOutput>
  </configuration>
  <executions>
    <execution>
      <id>spotbugs</id>
      <phase>verify</phase>
      <goals>
        <goal>check</goal>
      </goals>
    </execution>
  </executions>
</plugin>

PMD

  • pmd自体は6.11で解析する
  • rulesetは標準のルールを全て定義している
  • "[WARNING] Removed misconfigured rule: LoosePackageCoupling cause: No packages or classes specified"という警告が出力されるが、これはDesignルールセット内にあるLoosePackageCouplingが見つからないためである。
  • cpdのチェックも一緒に実施する。(cpdはコードの重複をチェックする)
  • failurePriorityでエラーとする規定値が変更できる。
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-pmd-plugin</artifactId>
  <version>3.11.0</version>
  <dependencies>
    <dependency>
      <groupId>net.sourceforge.pmd</groupId>
      <artifactId>pmd-core</artifactId>
      <version>6.11.0</version>
    </dependency>
    <dependency>
      <groupId>net.sourceforge.pmd</groupId>
      <artifactId>pmd-java</artifactId>
      <version>6.11.0</version>
    </dependency>
  </dependencies>
  <configuration>
    <rulesets>
      <ruleset>/category/java/bestpractices.xml</ruleset>
      <ruleset>/category/java/codestyle.xml</ruleset>
      <ruleset>/category/java/design.xml</ruleset>
      <ruleset>/category/java/documentation.xml</ruleset>
      <ruleset>/category/java/errorprone.xml</ruleset>
      <ruleset>/category/java/multithreading.xml</ruleset>
      <ruleset>/category/java/performance.xml</ruleset>
      <ruleset>/category/java/security.xml</ruleset>
    </rulesets>
    <targetJdk>${java.version}</targetJdk>
    <failOnViolation>true</failOnViolation>
    <failurePriority>0</failurePriority>
    <printFailingErrors>true</printFailingErrors>
    <verbose>true</verbose>
    <analysisCache>true</analysisCache>
  </configuration>
  <executions>
    <execution>
      <id>PMD</id>
      <phase>verify</phase>
      <goals>
        <goal>check</goal>
        <goal>cpd-check</goal>
      </goals>
    </execution>
  </executions>
</plugin>

OpenClover

  • カバレッジの割合を定義してcheckが出来、設定値を下回るとエラーとなる。
  • cloverゴールを実行することで、cloverフォルダおよびclover.xmlなどを出力する
<plugin>
  <groupId>org.openclover</groupId>
  <artifactId>clover-maven-plugin</artifactId>
  <version>4.3.1</version>
  <configuration>
    <targetPercentage>50%</targetPercentage>
    <failOnViolation>true</failOnViolation>
    <generateHtml>true</generateHtml>
    <generateXml>true</generateXml>
  </configuration>
  <executions>
    <execution>
      <id>check</id>
      <phase>verify</phase>
      <goals>
        <goal>instrument-test</goal>
        <goal>check</goal>
        <goal>clover</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Jacoco

  • Testのカバレッジを取得するだけなので、test-compile フェーズで実行する。
  • カバレッジの取得時にJVNに渡すjacocoArgsを生成し、maven-surefire-pluginで定義する
<plugin>
  <groupId>org.jacoco</groupId>
  <artifactId>jacoco-maven-plugin</artifactId>
  <version>0.8.3</version>
  <executions>
    <execution>
      <id>prepare-agent</id>
      <phase>test-compile</phase>
      <goals>
        <goal>prepare-agent</goal>
      </goals>
      <configuration>
        <propertyName>jacocoArgs</propertyName>
        <includes>
          <include>*</include>
        </includes>
      </configuration>
    </execution>
  </executions>
</plugin>

# タグにjacocoArgsを定義する
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-surefire-plugin</artifactId>
   <version>2.22.1</version>
   <configuration>
     <argLine>-Xmx256m ${jacocoArgs}</argLine>
   </configuration>
</plugin>

Jenkinsの設定例

JenkinsのBuildで静的解析も実行するだけならば、mvn clean varifyとすれば良い。
解析結果をレポートしたい場合mvn siteを実行する必要がなく、verifyで出力されるxmlファイルをPost-Build Actionで指定してあげるだけで良い。

Build

image.png

JUnit Test Report

image.png

OpenClover coverage report

image.png

JaCoCo Coverage report

image.png

その他の解析レポートは、Warnings Next Generation Pluginを使う

checkstyle, findbugs, PMDなどの個別のレポートプラグインはEOLになっており、Warning Next Generation Pluginに統合されたので、今回はこちらを使用してみた。

checkstyle

image.png

spotbugs

image.png

pmd

image.png

cmd

image.png

感想

検証に使ったソースコードではそれほどテストコードも無いにも関わらず、Jenkinsのビルド時間が7−8分掛かった。
(ローカルPCでJenkinsを動かしていることもあるだろうが)OpenCloverのために2回compileやtestを行なっているのも原因と思う。
OpenCloverの方がJaCoCoに比べ解析できる内容が広いが、OpenCloverを使うことでの副作用を考えるとJaCoCoだけを使った方が用意場合もある。

参考リンク

Apache Maven Plugins
Apache Maven Chackstyle Plugin
SpotBugs Maven Plugin
Apache Maven PMD Plugin
Clover Maven Plugin
OpenCloverでカバレッジを取得する
THE ULTIMATE CODE QUALITY SETUP FOR YOUR AEM PROJECT

15
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?