我们的系统一直使用Powermock做unit test的mock实现,之前就发现了Powermock在sonar的jacoco的测试覆盖率非常的低,所以我们一直使用cobertura作为我们的sonar测试覆盖率工具,在maven pom文件中使用cobertura的配置如下:
<properties>
....
<!-- define the plugin in sonar, not require after sonar 4.5 -->
<sonar.java.coveragePlugin>cobertura</sonar.java.coveragePlugin>
<!-- report path -->
<sonar.cobertura.reportPath>target/site/cobertura/cobertura.xml</sonar.cobertura.reportPath>
</properties>
<!-- plugin -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.6</version>
<configuration>
<formats>
<!-- generate xml report -->
<format>xml</format>
</formats>
<instrumentation>
<!-- ignore generated code -->
<ignore>com.cloud.generated.*</ignore>
</instrumentation>
</configuration>
<executions>
<execution>
<id>generate-report</id>
<phase>prepare-package</phase>
<goals>
<goal>cobertura</goal>
</goals>
</execution>
</executions>
</plugin>
这样在package phase就可以在sit/cobertura下看到cobertura的report,执行mvn sonar:sonar就可以扫描cobertura的结果做为test覆盖率。
Note1: sonar server必须安装了支持cobertura结果分析的plugin。
Note2:cobertura会额外多run一次test,在测试用例耗时不长的时候是件好事情,在测试失败的时候可以方便排查是否是cobertura instrument对测试产生了影响。
这一次公司系统环境迁移到新的sonar环境,就不再支持cobertura的配置,所以我们被迫需要转到jacoco测试覆盖率,可是Powermock和jacoco动态测试覆盖率实在不堪入目。我们在网上调查,发现有2种解决方案:
1. 静态Jacoco, offline instrument
2. Powermock Agent
这里先说第一种offline instrument,完整例子可以参考:http://www.eclemma.org/jacoco/trunk/doc/examples/build/pom-offline.xml
这里说说我用到的实现:
<properties>
....
<jacoco.version>0.7.8-SNAPSHOT</jacoco.version>
<!-- define ut/it report path, the same in our system due to sonar version is too old and doesn't support seperated it report-->
<sonar.jacoco.reportPath>${project.build.directory}/jacoco.exec</sonar.jacoco.reportPath>
<sonar.jacoco.itReportPath>${project.build.directory}/jacoco.exec</sonar.jacoco.itReportPath>
<!-- jacoco agent path for dymanic/static instrument-->
<sonar.jacoco.jar>${settings.localRepository}/org/jacoco/org.jacoco.agent/${jacoco.version}/org.jacoco.agent-${jacoco.version}-runtime.jar</sonar.jacoco.jar>
<!-- parameter used to control the instrument process, instrument for offline should only be used for ci phase not for loadbuild and package release -->
<jacoco.skip.instrument>true</jacoco.skip.instrument>
</properties>
<!-- include jacoco agent for instrument -->
<dependency>
<!-- must be on the classpath -->
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.agent</artifactId>
<classifier>runtime</classifier>
<version>${jacoco.version}</version>
<scope>test</scope>
</dependency>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<configuration>
<excludes>
<exclude>com.cloud.generated.*</exclude>
</excludes>
<skip>${jacoco.skip.instrument}</skip>
</configuration>
<executions>
<execution>
<id>default-instrument</id>
<goals>
<goal>instrument</goal>
</goals>
</execution>
<execution>
<id>default-restore-instrumented-classes</id>
<goals>
<goal>restore-instrumented-classes</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.13</version>
<configuration>
<argLine>-XX:-UseSplitVerifier -javaagent:${sonar.jacoco.jar}=destfile=${sonar.jacoco.reportPath,includes=com.cloud.codes}</argLine>
<excludes>
<exclude>**/*IntegerationTest.java</exclude>
</configuration>
</plugin>
</plugins>
这种实现的问题主要在于支持不够,offline instrument在我们的系统测试过程中对powermockito和openjpa的支持很差,只好放弃选择方案2。方案二的实现在下一次的blog中细说。