SonarQubeでMavenのレポートを再利用する設定

最近リリースされたSonarQube 4.3から、SonarQube実行時にユニットテストを実行する機能である sonar.dynamicAnalysis が非推奨になりました。*1 SonarQube自身が様々なの言語への対応を進める中で、各言語のテストフレームワーク全てを実行できるようにするのは無理があるので、この変更は仕方のないものだと思います。

自分のプロジェクトでも対応が必要になったので、どう設定したかなどまとめておきます。

Unit Test、Integration Testの実行設定

テスト実行に前提条件(DBのセットアップ、コンテナ起動など)がある場合、JUnitのカテゴリ機能を利用して実行可否を制御しておくと便利ですよね。 うちのプロジェクトでは、環境に依存せずサクサク動くテストはsurefireで実行し、DBFluteのReplaceSchemaでデータベースをセットアップしたり、SpringのWebApplicationContextを利用するような重いテストはfailsafeで実行するようにしています。

SonarではUnit TestとIntegration Testを分けてカバレッジを出せるので、surefireをUnit Test、failsafeをIntegration Testとすることにし、以下のように設定しました。

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.17</version>
                <configuration>
                    <excludedGroups>
                        com.example.IntegrationTest
                    </excludedGroups>
                    <argLine>${argLine}</argLine>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.17</version>
                <configuration>
                    <includes>
                        <include>**/*Test.java</include>
                    </includes>
                    <groups>com.example.IntegrationTest</groups>
                    <failIfNoTests>false</failIfNoTests>
                    <argLine>${argLine}</argLine>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>2.17</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

<profiles>
    <profile>
        <id>sonar</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <testFailureIgnore>true</testFailureIgnore>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-failsafe-plugin</artifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>integration-test</goal>
                                <goal>verify</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <testFailureIgnore>true</testFailureIgnore>
                        <reportsDirectory>${project.build.directory}/surefire-reports</reportsDirectory>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

pluginManagementにて、Integration Testの目印としたcom.example.IntegrationTestカテゴリを、surefireからは除外、failsafeには対象として、それぞれ設定します。 また、sonarプロファイルでfailsafeが実行されるようexecutionを設定しています。

今回はIntegration Testの件数もSonarでカウントしてもらいたかったので、failsafeのreportsDirectorysurefireと同じ場所に設定しました。

テストカバレッジを取得する

テストカバレッジの取得にはjacocoを使用します。これもSonar実行時のみ行えばよいので、sonarプロファイルに設定を追加します。

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.0.201403182114</version>
    <executions>
        <execution>
            <id>pre-test</id>
            <goals><goal>prepare-agent</goal></goals>
        </execution>
        <execution>
            <id>post-test</id>
            <goals><goal>report</goal></goals>
        </execution>
        <execution>
            <id>pre-integration-test</id>
            <phase>pre-integration-test</phase>
            <goals><goal>prepare-agent-integration</goal></goals>
        </execution>
        <execution>
            <id>post-integration-test</id>
            <phase>post-integration-test</phase>
            <goals><goal>report-integration</goal></goals>
        </execution>
    </executions>
</plugin>

report|report-integrationゴールで、target/jacoco.exec|target/jacoco-it.execが出力されます。Sonarの解析時、これらのファイルを再利用することになります。

実行

ここまで設定したら、後はSonarで解析を実行するだけです。最初にMavensonarプロファイルでverifyフェーズまでビルドしておき、SonarRunnerを実行します。

Mavenでやるならこんな感じで。

mvn -P sonar verify
mvn sonar:sonar

Jenkinsであれば、Mavenプロジェクトとしてジョブを作成し、ビルド後にSonarプラグインが動くようにすればOKです。