简体   繁体   English

Gradle 使用 JaCoCo 代码覆盖的多项目构建在使用 Spring 引导时失败

[英]Gradle Multi-Project Build with JaCoCo Code Coverage fails when using Spring Boot

Starting with the sample from https://docs.gradle.org/current/samples/sample_jvm_multi_project_with_code_coverage.html (ie, the code here https://github.com/gradle/gradle/tree/master/subprojects/docs/src/samples/java/jvm-multi-project-with-code-coverage ) and simply adding Spring Boot by changing application/build.gradle to Starting with the sample from https://docs.gradle.org/current/samples/sample_jvm_multi_project_with_code_coverage.html (ie, the code here https://github.com/gradle/gradle/tree/master/subprojects/docs/src/ samples/java/jvm-multi-project-with-code-coverage )并通过将application/build.gradle更改为简单地添加 Spring Boot

plugins {
    id 'myproject.java-conventions'
    id 'application'
}

dependencies {
    implementation project(':list')
    implementation project(':utilities')
    implementation 'org.springframework.boot:spring-boot-starter-web:2.3.8.RELEASE' // <-- this line is new
}

application {
    mainClass = 'org.gradle.sample.Main'
}

and changing application/src/main/java/org/gradle/sample/app/Main.java to并将application/src/main/java/org/gradle/sample/app/Main.java

package org.gradle.sample.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.gradle.sample.list.LinkedList;

import static org.gradle.sample.utilities.StringUtils.join;
import static org.gradle.sample.utilities.StringUtils.split;
import static org.gradle.sample.app.MessageUtils.getMessage;

@SpringBootApplication
public class Main {
    public static void main(String[] args) {
        LinkedList tokens;
        tokens = split(getMessage());
        System.out.println(join(tokens));
        SpringApplication.run(Main.class, args);
    }
}

will break the example (full working, or rather non-working example here: https://github.com/SamuelBucheliZ/gradle-jvm-multi-project-with-code-coverage/tree/57e57b8bf24ef4208d9a03a361714c916701e599 ).将打破这个例子(完整的工作,或者更确切地说是非工作的例子: https://github.com/SamuelBucheliZ/gradle-jvm-multi-project-with-code-coverage/tree/57e57b8bf24ef4208d9a03a361714c916701e599 )。

When calling打电话时

./gradlew clean build codeCoverage -stacktrace

it will fail with它会失败

> Task :code-coverage-report:codeCoverageReport FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':code-coverage-report:codeCoverageReport'.
> Error while creating report

* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':code-coverage-report:codeCoverageReport'.
        [...]
Caused by: java.io.IOException: Error while analyzing log4j-api-2.13.3.jar@org/apache/logging/log4j/util/ProcessIdUtil.class.
        at org.jacoco.core.analysis.Analyzer.analyzerError(Analyzer.java:162)
        at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:134)
        at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:157)
        at org.jacoco.core.analysis.Analyzer.analyzeAll(Analyzer.java:193)
        at org.jacoco.core.analysis.Analyzer.analyzeZip(Analyzer.java:265)
        at org.jacoco.core.analysis.Analyzer.analyzeAll(Analyzer.java:196)
        at org.jacoco.ant.ReportTask.createBundle(ReportTask.java:573)
        at org.jacoco.ant.ReportTask.createReport(ReportTask.java:545)
        at org.jacoco.ant.ReportTask.execute(ReportTask.java:496)
        ... 251 more
Caused by: java.lang.IllegalStateException: Can't add different class with same name: org/apache/logging/log4j/util/ProcessIdUtil
        at org.jacoco.core.analysis.CoverageBuilder.visitCoverage(CoverageBuilder.java:106)
        at org.jacoco.core.analysis.Analyzer$1.visitEnd(Analyzer.java:99)
        at org.objectweb.asm.ClassVisitor.visitEnd(ClassVisitor.java:378)
        at org.jacoco.core.internal.flow.ClassProbesAdapter.visitEnd(ClassProbesAdapter.java:100)
        at org.objectweb.asm.ClassReader.accept(ClassReader.java:722)
        at org.objectweb.asm.ClassReader.accept(ClassReader.java:401)
        at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:116)
        at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:132)
        ... 258 more


* Get more help at https://help.gradle.org

BUILD FAILED in 8s
19 actionable tasks: 19 executed

I have a suspicion that this may be related to https://github.com/jacoco/jacoco/issues/407 .我怀疑这可能与https://github.com/jacoco/jacoco/issues/407有关。 However, my question is whether there is any way to fix this problem.但是,我的问题是是否有任何方法可以解决此问题。 Unfortunately, the official documentation at https://docs.gradle.org/current/userguide/jacoco_plugin.html does not provide any guidance on this topic.不幸的是, https://docs.gradle.org/current/userguide/jacoco_plugin.html的官方文档没有提供关于这个主题的任何指导。

As far as I can tell, the problematic line is https://github.com/SamuelBucheliZ/gradle-jvm-multi-project-with-code-coverage/blob/57e57b8bf24ef4208d9a03a361714c916701e599/buildSrc/src/main/groovy/myproject.jacoco-aggregation.gradle#L38据我所知,有问题的行是https://github.com/SamuelBucheliZ/gradle-jvm-multi-project-with-code-coverage/blob/57e57b8bf24ef4208d9a03a361714c916701e599/buildSrc/scorc/main/groovyproject。 -aggregation.gradle#L38

// Task to gather code coverage from multiple subprojects
def codeCoverageReport = tasks.register('codeCoverageReport', JacocoReport) {
    additionalClassDirs(configurations.runtimeClasspath) // <-- this line here
    additionalSourceDirs(sourcesPath.incoming.artifactView { lenient(true) }.files)
    executionData(coverageDataPath.incoming.artifactView { lenient(true) }.files.filter { it.exists() })

    reports {
        // xml is usually used to integrate code coverage with
        // other tools like SonarQube, Coveralls or Codecov
        xml.enabled true

        // HTML reports can be used to see code coverage
        // without any external tools
        html.enabled true
    }
}

Removing it will make the build work again.删除它将使构建再次工作。 However, then the code coverage report is empty.但是,代码覆盖率报告是空的。 Is there any way to adjust it, so it will only include code from the project itself, but not external jars, etc.?有没有办法调整它,所以它只会包含来自项目本身的代码,而不包含外部 jars 等?

Just do that and you will be fine (all external classes will be excluded):只要这样做,你会没事的(所有外部类都将被排除在外):

additionalClassDirs(configurations.runtimeClasspath.get().filter{it.path.contains(rootProject.name)  })

This works with a Kotlin DSL, with Groovy you might have to change the code a little bit maybe this way:这适用于 Kotlin DSL,对于 Groovy,您可能需要通过以下方式稍微更改代码:

additionalClassDirs(configurations.runtimeClasspath.filter{it.path.contains(rootProject.name)  })

One possible approach is to define一种可能的方法是定义

def sourcesOutputPath = configurations.create("sourcesOutputPath") {
    visible = false
    canBeResolved = true
    canBeConsumed = false
    extendsFrom(configurations.implementation)
    attributes {
        attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME))
        attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.DOCUMENTATION))
        attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, 'source-output-folders'))
    }
}

and then use it in然后在

additionalClassDirs(sourcesOutputPath.incoming.artifactView { lenient(true) }.files)

instead of代替

additionalClassDirs(configurations.runtimeClasspath)

A full, working setup can be found in https://github.com/SamuelBucheliZ/gradle-jvm-multi-project-with-code-coveragehttps://github.com/SamuelBucheliZ/gradle-jvm-multi-project-with-code-coverage中可以找到完整的工作设置

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Gradle:使用 spring-boot 进行多项目构建 - Gradle: multi-project build with spring-boot 如何忽略 gradle 为多项目 Kotlin Spring 启动应用程序构建的根项目? - How to ignore gradle build of root project for a multi-project Kotlin Spring Boot application? Spring 引导 Gradle 多项目构建在测试期间看不到内部依赖项 - Spring Boot Gradle multi-project build not seeing internal dependencies during tests Spring Boot Gradle插件“祝福”多项目环境中的依赖关系 - Spring Boot Gradle Plugin “Blessed” Dependencies in a multi-project environment Gradle 多项目存储库配置不适用于 spring-boot 应用程序 - Gradle multi-project repository configuration not working for spring-boot application Gradle多项目构建命令失败,但对子项目可正常使用 - Gradle multi-project build command fails but works correctly for sub-projects 如何在 Gradle 多项目构建中引用其他类目录 - How to reference other classesdir in Gradle multi-project build 在gradle多项目中,如何构建单个jar并将其发布到maven? - In gradle multi-project, how to build single jar and publish it to maven? 带有 Gradle 的 Spring Boot 多模块项目无法构建 - Spring Boot multi module project with Gradle doesn't build 如何从 Gradle Multi Build 项目发布 Spring Boot 应用程序? - How to ship a Spring Boot app from a Gradle Multi Build project?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM