如何使用jacoco检查多模块maven项目的最小代码覆盖率?

问题描述 投票:0回答:3

我想使用

jacoco maven plugin
在构建过程中使用
'check'
目标检查最低级别的代码覆盖率。

对于单模块项目,一切正常。 但对于多模块,我想检查所有模块的代码覆盖率的平均水平,但

check
目标分别检查每个模块。

例如,module1 的代码覆盖率为 70%module2 的代码覆盖率为 100%,两个模块中所有行的平均代码覆盖率为 85%。 我尝试将所有项目的代码覆盖率设置为 80%,但由于第一个模块而失败。

来自 pom:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.6.201602180812</version>
    <executions>
        <execution>
            <id>default-prepare-agent</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>default-report</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
        <execution>
            <id>default-check</id>
            <goals>
                <goal>check</goal>
            </goals>
            <configuration>
                <rules>
                    <rule>
                        <element>BUNDLE</element>
                        <limits>
                            <limit>
                                <counter>COMPLEXITY</counter>
                                <value>COVEREDRATIO</value>
                                <minimum>0.80</minimum>
                            </limit>
                        </limits>
                    </rule>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>
maven testing code-coverage jacoco-maven-plugin
3个回答
5
投票

简短的回答:(在撰写本文时)仅使用 Maven 和 Jacoco 是不可能的。

来自官方 jacoco github 页面:

当前的 JaCoCo Maven 目标仅适用于单个模块:测试在模块内执行,并且仅对同一模块内的代码提供覆盖范围。覆盖率报告是为每个模块单独创建的。没有对跨模块覆盖或多个模块的组合报告的内置支持。

因此仅使用 Maven 和 Jacoco 无法满足您的要求。但是,您可以在企业设置中使用通用方法:Sonarqube,它将处理生成的 jacoco 文件(即

jacoco.exec
)并通过其 Jacoco 集成(在最新版本上开箱即用)聚合报告和治理。


0
投票

来源:https://www.jacoco.org/jacoco/trunk/doc/check-mojo.html

使用带有计数器指令的 Bundle,这将检查整个项目的整体代码覆盖率:

<rules>
<rule>
    <element>BUNDLE</element>
    <limits>
        <limit>
            <counter>INSTRUCTION</counter>
            <value>COVEREDRATIO</value>
            <minimum>0.80</minimum>
        </limit>
    </limits>
</rule>

0
投票

不可能(到目前为止,希望将来也是如此)。但我有另一种方法可以做到这一点。

Jacoco 的目标是为多模块项目创建聚合报告,但它不会创建检查覆盖率指标所需的 jacoco.exec 文件。

一种方法是使用report-aggregate goal创建聚合报告,并为每个模块单独生成jacoco.exec文件,然后使用jacoco-merge goal将其合并。

但是这种方法并不是那么好,因为它只覆盖了直接代码覆盖率。 例如-> 假设你的模块 A 有一些测试覆盖了模块 B 中的某些代码行,在这种情况下合并不会考虑此模块级别的差异,这是因为你首先生成模块级别的 exec 文件,然后将其合并为一个。

我找到了一种更好的总体检查方法。这不需要任何执行文件,您可以仅使用报告聚合目标来完成! 如果您注意到报告聚合目标确实为聚合报告创建了 html、xml 和 csv 文件,我们可以简单地从这些文件中抓取数据并编写验证!

这是我使用 XML 文件实现的

        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>${jacoco-maven-plugin.version}</version>
            <executions>
                <execution>
                    <id>prepare-agent</id>
                    <goals>
                        <goal>prepare-agent</goal>
                    </goals>
                </execution>
                <!--  Aggregate the report after tests run -->
                <execution>
                    <id>report-aggregate</id>
                    <phase>verify</phase>
                    <goals>
                        <goal>report-aggregate</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>
                            ${project.basedir}/target/jacoco-reports
                        </outputDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.6.0</version>
            <executions>
                <execution>
                    <phase>verify</phase>
                    <goals>
                        <goal>exec</goal>
                    </goals>
                    <configuration>
                        <executable>python3</executable>
                        <arguments>
                            <argument>check_coverage.py</argument>
                            <argument>${code-coverage-percentage}</argument>
                        </arguments>
                    </configuration>
                </execution>
            </executions>
        </plugin>

check_coverage.py

import xml.etree.ElementTree as ET
import sys

# Path to the JaCoCo XML report file
jacoco_report_file = 'target/jacoco-reports/jacoco.xml'

# Get the required coverage from the command-line argument
try:
    required_coverage = float(sys.argv[1])  # Pass as first argument
except IndexError:
    print("Usage: python check_coverage.py <required_coverage>")
    sys.exit(1)
except ValueError:
    print("Invalid value for required coverage, please provide a numeric value.")
    sys.exit(1)


try:
    # Parse the XML file
    tree = ET.parse(jacoco_report_file)
    root = tree.getroot()

    # Find the line coverage data
    counter = root.findall(".//counter[@type='LINE']")
    if not counter:
        print("Could not find line coverage data in the JaCoCo report.")
        exit(1)

    # Pick the last occurrence
    last_counter = counter[-1]

    # Extract the 'missed' and 'covered' values from the XML
    missed = int(last_counter.get('missed', 0))
    covered = int(last_counter.get('covered', 0))
    print(missed)
    print(covered)

    # Calculate the total lines and the line coverage percentage
    total_lines = missed + covered
    if total_lines == 0:
        print("No lines were executed or missed, cannot calculate coverage.")
        exit(1)

    line_coverage = (covered / total_lines) * 100

    # Output the calculated coverage
    print(f"Line Coverage: {line_coverage:.2f}%")

    # Check if the coverage meets the required threshold (e.g., 80%)
    # required_coverage = 80.0  # Set your desired threshold here
    if line_coverage < required_coverage:
        print(f"Coverage is below the required threshold of {required_coverage}%.")
        exit(1)
    else:
        print("Coverage meets the required threshold.")
        exit(0)

except FileNotFoundError:
    print(f"JaCoCo aggregate report not found at {jacoco_report_file}.")
    exit(1)

except ET.ParseError as e:
    print(f"Error parsing the JaCoCo XML report: {e}")
    exit(1)

只需根据您的要求调整代码覆盖率

维奥拉!

© www.soinside.com 2019 - 2024. All rights reserved.