cobertura在maven多模块项目上

时间:2009-09-14 10:21:54

标签: maven-2 cobertura

我有一个包含4个模块的Maven项目 - 其中3个包含代码和一些测试(测试等于和类的哈希码),而第4个模块用于测试其他3个模块。

现在我想运行cobertura代码覆盖率工具来概览哪些类经过了充分测试,哪些不是。我对该主题进行了一些调查,如果测试的某些源位于其他模块中,则cobertura似乎不知道生成正确的代码覆盖百分比和线路覆盖率。

我已阅读过SeamTestCoverageWithCoberturaUsing the plugin Coverage within a multi-module Maven 2等链接,但必须有一个开箱即用的解决方案。有人可以报告一些关于这个主题的新方向吗?还是有像cobertura这样的工具?我偶然发现了艾玛,但这个工具不提供线路覆盖......

7 个答案:

答案 0 :(得分:19)

从版本2.6开始,在父pom中有一个可以设置为true的聚合选项:

<reporting>
<plugins>
  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>cobertura-maven-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <outputDirectory>./target/tmpCobertura</outputDirectory>
        <formats>
            <format>html</format>
        </formats>
        <aggregate>true</aggregate>
    </configuration>
  </plugin>
</plugins>
</reporting>

答案 1 :(得分:9)

我们现在没有声纳,我们无法安装它。所以我必须找到一个解决方法并得到一个。此解决方案适用于多模块项目中的简单mvn clean install -DrunCobertura=true。您只需要将此配置文件添加到项目的super pom.xml,定义working.dir属性即可。

<profile>
    <id>runCobertura</id>
    <activation>
        <property>
            <name>runCobertura</name>
            <value>true</value>
        </property>
    </activation>
    <properties>
        <cobertura.format>html</cobertura.format>
        <cobertura.working.dir>${working.dir}/${project.version}/cobertura</cobertura.working.dir>
        <cobertura.complete.ser.file>${cobertura.working.dir}/complete.ser</cobertura.complete.ser.file>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-clean-plugin</artifactId>
                <version>2.4.1</version>
                <inherited>false</inherited>
                <configuration>
                    <filesets>
                        <fileset>
                            <directory>.</directory>
                            <includes>
                                <include>cobertura.ser</include>
                            </includes>
                        </fileset>
                        <fileset>
                                <directory>${cobertura.working.dir}</directory>
                            </fileset>
                    </filesets>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.7</version>
                <executions>
                    <execution>
                        <id>cobertura-Instrument</id>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <taskdef resource="tasks.properties"/>
                                <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                <if>
                                    <available file="${project.build.outputDirectory}"/>
                                    <then>
                                        <cobertura-instrument>
                                            <fileset dir="${project.build.outputDirectory}">
                                                <include name="**/*.class"/>
                                            </fileset>
                                        </cobertura-instrument>
                                    </then>
                                </if>
                            </target>
                        </configuration>
                    </execution>
                    <execution>
                        <id>cobertura-createCombinedSerFile</id>
                        <phase>generate-test-sources</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <taskdef resource="tasks.properties"/>
                                <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                <if>
                                    <available file="${cobertura.complete.ser.file}"/>
                                    <then>
                                        <cobertura-merge datafile="${basedir}/tmp.ser">
                                            <fileset file="${cobertura.complete.ser.file}"/>
                                            <fileset file="${basedir}/cobertura.ser"/>
                                        </cobertura-merge>
                                        <move file="${basedir}/tmp.ser" tofile="${basedir}/cobertura.ser"/>
                                    </then>
                                </if>
                            </target>
                        </configuration>
                    </execution>
                    <execution>
                        <id>cobertura-copyResultSerFileAndSources</id>
                        <phase>test</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <taskdef resource="tasks.properties"/>
                                <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                <if>
                                    <available file="${basedir}/cobertura.ser"/>
                                    <then>
                                        <move file="${basedir}/cobertura.ser" tofile="${cobertura.complete.ser.file}"/>
                                        <mkdir dir="${cobertura.working.dir}/source"/>
                                        <if>
                                            <available file="${basedir}/src/main/java"/>
                                            <then>
                                                <copy todir="${cobertura.working.dir}/source">
                                                    <fileset dir="src/main/java">
                                                        <include name="**/*.java"/>
                                                    </fileset>
                                                </copy>
                                            </then>
                                        </if>
                                        <cobertura-report datafile="${cobertura.complete.ser.file}" format="${cobertura.format}" destdir="${cobertura.working.dir}/report">
                                            <fileset dir="${cobertura.working.dir}/source"/>
                                        </cobertura-report>
                                    </then>
                                </if>
                            </target>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>net.sourceforge.cobertura</groupId>
                        <artifactId>cobertura</artifactId>
                        <version>1.9.4.1</version>
                    </dependency>
                    <dependency>
                        <groupId>ant-contrib</groupId>
                        <artifactId>ant-contrib</artifactId>
                        <version>20020829</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>net.sourceforge.cobertura</groupId>
            <artifactId>cobertura</artifactId>
            <version>1.9.4.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</profile>

它做了什么:

1。 @process-classes - 检测模块的已编译类。

2. @generate-test-sources - 将以前模块中的.ser文件与此模块中创建的文件合并,以获得完整的代码覆盖率。

3. @test - 创建代码覆盖率报告。应该在最后一个模块中调用,但由于最后一个模块可以更改,我总是调用它,之前的报告将被覆盖。如果您使用xml格式的报告(对于詹金斯来说)速度很快,那么这并不重要。

答案 2 :(得分:8)

根据MCOBERTURA-65,maven cobertura插件仍然不知道如何将子模块的报告聚合成一个统一的子模块。已经完成了一些工作来实现maven cobertura插件上的merge目标(请参阅MCOBERTURA-33),但此代码尚未包含在插件中。我自己没有测试补丁,也不能说是否值得一试。

因此,很多人确实建议使用maven dashboard plugin,但我个人会远离它,因为从长远来看它不是很令人满意,我遇到了很多问题(技术问题,历史遗失,......)。相反,我热烈推荐Sonar 。查看最新版Sonar的公共实例Nemo,了解此工具的实时演示。例如,请参阅Commons Digester项目和drill down of code coverage

答案 3 :(得分:3)

有一些插件汇总了Cobertura(和其他)报告。查看sonarXRadar插件。还有dashboard plugin,但它有点笨重。

FWIW Emma确实line coverage

答案 4 :(得分:2)

我真的要感谢Sven Oppermann提交他的runCobertura配置文件解决方案。这有帮助 我解决了“如何获得多模块项目的聚合覆盖率报告”的问题 能够使用声纳。

我创建了一个示例,演示了如何创建多模块项目,这些项目生成的代码覆盖率报告不仅可以评估单元测试覆盖率(在所有子模块中),还可以覆盖集成测试的覆盖范围。 在JETTY中将你的应用程序作为.WAR。这个例子在这里托管:

        http://dl.dropbox.com/u/9940067/code/multi-module-cobertura.zip 

如果您复制下面列出的runCobertura配置文件(基于一个),我提供的配方非常可重复使用 由斯文提供。)

以下是一些有助于您使用此个人资料的说明:

  • 启动jetty的集成测试模块(并定义运行的测试   生产.war)必须被命名为web-test-driver-for-code-coverage,或者你    必须修改runCobertura配置块中的语句。

  • 只要您设置变量

  • ,您的报道就会出现
  • 在运行代码覆盖的构建时,必须在命令行中包含“clean”。 'clean'会先泄漏cobertura.ser文件,   如果留下潜伏,可能会引起非常混乱的报道    生成(需要'清理'的标志是报告显示的   100%覆盖所有内容,包括您从未调用的内容。

      mvn -PrunCobertura clean install      # gives you the aggregate reports.
    
  • 模块web-test-driver-for-code-coverage定义了一个servlet上下文监听器,它将cobertura指标显式刷新到磁盘   当Web服务器关闭时。据说容器应该自动执行此操作,但这对我不起作用,所以   我不得不在显式调用中挂钩以清除指标。

  • 集成测试是在groovy中完成的,因为我基于已经使用了groovy的一些maven项目骨架。   对不起添加的混乱,但它确实向您展示如何在groovy中进行测试(无论如何强烈建议。)

  • 请注意,使用runCobertura配置文件进行编译时,所有工件都是使用cobertura工具创建的,甚至是   .war文件。你当然不想让它在生产过程中出现(有一件事情它将会运行得很慢。)我没有   然而想出了一种让食物重新命名的食物方式,以便'cobertura-ness'显而易见。

    <profiles>
    <profile>
        <id>runCobertura</id>
        <activation>
            <property>
                <name>runCobertura</name>
                <value>true</value>
            </property>
        </activation>
        <properties>
            <cobertura.format>html</cobertura.format>
            <working.dir>/tmp</working.dir>
            <cobertura.working.dir>${working.dir}/${project.version}/cobertura</cobertura.working.dir>
            <cobertura.complete.ser.file>${cobertura.working.dir}/complete.ser</cobertura.complete.ser.file>
    
            <!-- scope which determines whether or not cobertura is included in .war file: overriden here -->
            <cobertura.dependency.scope>compile</cobertura.dependency.scope>
        </properties>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>2.4.1</version>
                    <inherited>false</inherited>
                    <configuration>
                        <filesets>
                            <fileset>
                                <directory>.</directory>
                                <includes>
                                    <include>**/cobertura.ser</include>
                                </includes>
                            </fileset>
                            <fileset>
                                    <directory>${cobertura.working.dir}</directory>
                                </fileset>
                        </filesets>
                    </configuration>
                </plugin>
    
    
    
    
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <version>1.7</version>
                    <executions>
                        <execution>
                            <id>cobertura-Instrument</id>
                            <phase>process-classes</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <target>
                                    <taskdef resource="tasks.properties"/>
                                    <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                    <echo message="::PROCESS CLASSES: ${artifactId}"/>
    
                                    <if>
                                      <equals arg1="${artifactId}" arg2="web-test-driver-for-code-coverage" />
                                        <then>
                                            <echo message="::SKIPPING PHASE for integration test"/>
                                        </then>
                                        <else>
                                            <if>
                                                <available file="${project.build.outputDirectory}"/>
                                                <then>
                                                    <echo message="::BEFORE INSTRUMENT"/>
                                                    <cobertura-instrument>
                                                        <fileset dir="${project.build.outputDirectory}">
                                                            <include name="**/*.class"/>
                                                        </fileset>
                                                    </cobertura-instrument>
                                                </then>
                                            </if>
                                        </else>
                                    </if>
    
    
                                </target>
                            </configuration>
                        </execution>
                        <execution>
                            <id>cobertura-createCombinedSerFile</id>
                            <phase>generate-test-sources</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <target>
                                    <taskdef resource="tasks.properties"/>
                                    <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                    <echo message=":::generate-test-sources"/>
    
    
                                    <if>
                                      <equals arg1="${artifactId}" arg2="web-test-driver-for-code-coverage" />
                                        <then>
                                            <echo message="::SHORT CIRCUIT COMBINE PHASE for integration test"/>
                                            <echo  message="source - ${cobertura.complete.ser.file} dest - ${basedir}/cobertura.ser"/>
                                            <copy file="${cobertura.complete.ser.file}" tofile="${basedir}/cobertura.ser"/>
                                        </then>
                                        <else>
                                            <if>
                                                <available file="${basedir}/cobertura.ser"/>
                                                <then>
                                                    <echo message="::: Is available ${basedir}/cobertura.ser"/>
                                                </then>
                                            </if>
    
                                            <if>
                                                <available file="${cobertura.complete.ser.file}"/>
                                                <then>
                                                    <echo message="before merge1"/>
                                                    <cobertura-merge datafile="${basedir}/tmp.ser">
                                                        <fileset file="${cobertura.complete.ser.file}"/>
                                                        <fileset file="${basedir}/cobertura.ser"/>
                                                    </cobertura-merge>
                                                    <echo message="move temp.ser to ${basedir}/cobertura.ser"/>
                                                    <move file="${basedir}/tmp.ser" tofile="${basedir}/cobertura.ser"/>
                                                </then>
                                            </if>
                                        </else>
                                    </if>
                                </target>
                            </configuration>
                        </execution>
                        <execution>
                            <id>cobertura-copyResultSerFileAndSources</id>
                            <phase>verify</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <target>
                                    <taskdef resource="tasks.properties"/>
                                    <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
    
                                    <echo message=":::copyResultSerFileAndSources -beforeIf"/>
                                    <if>
                                        <available file="${basedir}/cobertura.ser"/>
                                        <then>
                                            <echo message="move1"/>
                                            <move file="${basedir}/cobertura.ser" tofile="${cobertura.complete.ser.file}"/>
                                            <mkdir dir="${cobertura.working.dir}/source"/>
                                            <if>
                                                <available file="${basedir}/src/main/java"/>
                                                <then>
                                                    <copy todir="${cobertura.working.dir}/source">
                                                        <fileset dir="src/main/java">
                                                            <include name="**/*.java"/>
                                                        </fileset>
                                                    </copy>
                                                </then>
                                            </if>
                                            <echo message="runreport"/>
                                            <cobertura-report datafile="${cobertura.complete.ser.file}" format="${cobertura.format}" destdir="${cobertura.working.dir}/report">
                                                <fileset dir="${cobertura.working.dir}/source"/>
                                            </cobertura-report>
                                        </then>
                                    </if>
                                </target>
                            </configuration>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>net.sourceforge.cobertura</groupId>
                            <artifactId>cobertura</artifactId>
                            <version>1.9.4.1</version>
                        </dependency>
                        <dependency>
                            <groupId>ant-contrib</groupId>
                            <artifactId>ant-contrib</artifactId>
                            <version>20020829</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </build>
        <dependencies>
            <dependency>
                <groupId>net.sourceforge.cobertura</groupId>
                <artifactId>cobertura</artifactId>
                <version>1.9.4.1</version>
            </dependency>
        </dependencies>
    </profile>
    </profiles>
    

答案 5 :(得分:1)

Thomas Sundberg提供了一个有趣的解决方案,其中检测和测试报告通过ant完成,但所有测试和依赖管理都通过mvn完成。

点击此处: thomassundberg wordpress

这意味着您必须按以下顺序在父级别执行以下命令:

mvn clean compile
ant instrument
mvn test
ant report

Martijn Stelinga描述了将这些步骤整合到sonar中。

test-coverage-in-multi-module-projects

答案 6 :(得分:0)

由于这个答案,我可以实现与你需要的东西非常相似的东西:Maven - add dependency on artifact source

我刚刚添加了<classifier>sources</classifier>,cobertura也包含了依赖项中的类。

问候。