Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Determine how to use jacoco plugin to get coverage for integration tests #32

Open
mkobit opened this issue Nov 22, 2017 · 14 comments
Open

Comments

@mkobit
Copy link
Owner

mkobit commented Nov 22, 2017

For unit tests it is straight forward and just works out of the box with the JaCoCo plugin (id 'jacoco'). Integration tests are more likely to be used to flex the execution, so coverage is important to have.

@mkobit mkobit added this to the 0.4.0 milestone Nov 22, 2017
@mkobit
Copy link
Owner Author

mkobit commented Jan 5, 2018

Removing from 0.4.0 - unit test coverage is easy but getting integration test coverage may be more difficult due to magic compilation by Jenkins

@mkobit mkobit removed this from the 0.4.0 milestone Jan 5, 2018
@markguckian
Copy link

Hi - could you provide info on how to add jacoco code coverage to unit tests? I've tried but no success. Thanks.

@mkobit
Copy link
Owner Author

mkobit commented Feb 16, 2018

Hey @markguckian can you add what you have tried here? It might help find the right path to get this figured out.

I'd like to get this working using Gradle's built in JaCoCo support, but I haven't figured it out yet. I think part of the issue is that general usage with JaCoCo/Gradle is that the input is compiled code and exec data and it will generate reports for that. With Jenkins Pipelines, the input is source code that gets compiled in a different fashion, so the out-of-the-box usage of JaCoCo does not work. I just get 0 coverage for the integration tests.

Here is what I tried in my example project at commit 8e7dbde714b33254c5faf1fb6dd2408e4f08d2d2:

import com.gradle.scan.plugin.BuildScanPlugin
import org.gradle.kotlin.dsl.version
import java.io.ByteArrayOutputStream

plugins {
  `jacoco`
  id("com.gradle.build-scan") version "1.11"
  id("com.mkobit.jenkins.pipelines.shared-library") version "0.4.0"
  id("com.github.ben-manes.versions") version "0.17.0"
}

jacoco {
  toolVersion = "0.8.0"
}

val commitSha: String by lazy {
  ByteArrayOutputStream().use {
    project.exec {
      commandLine("git", "rev-parse", "HEAD")
      standardOutput = it
    }
    it.toString(Charsets.UTF_8.name()).trim()
  }
}

buildScan {
  setLicenseAgree("yes")
  setLicenseAgreementUrl("https://gradle.com/terms-of-service")
  link("GitHub", "https://github.com/mkobit/jenkins-pipeline-shared-library-example")
  value("Revision", commitSha)
}

tasks {
  "wrapper"(Wrapper::class) {
    gradleVersion = "4.4.1"
  }
  "jacocoIntegrationTestReport"(JacocoReport::class) {
    reports {
      csv.setEnabled(true)
      xml.setEnabled(true)
    }
    executionData(tasks["integrationTest"])
    val main by java.sourceSets
    sourceSets(main)
  }
}

java {
  sourceCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
  testImplementation("org.spockframework:spock-core:1.1-groovy-2.4")
  testImplementation("org.assertj:assertj-core:3.9.0")
}

sharedLibrary {
  coreVersion = "2.95"
  groovyVersion = "2.4.12"
  pluginDependencies(Action {
    dependency("org.jenkinsci.plugins", "pipeline-model-api", "1.2.5")
    dependency("org.jenkinsci.plugins", "pipeline-model-declarative-agent", "1.1.1")
    dependency("org.jenkinsci.plugins", "pipeline-model-definition", "1.2.5")
    dependency("org.jenkinsci.plugins", "pipeline-model-extensions", "1.2.5")
  })
}

Running the jacocoIntegrationTestReport task results in a 0 coverage report with some standard out:

[ant:jacocoReport] Classes in bundle 'jenkins-pipeline-shared-library-example' do no match with execution data. For report generation the same class files must be used as at runtime.        
[ant:jacocoReport] Execution data for class doStuff does not match.                                                            
[ant:jacocoReport] Execution data for class evenOrOdd does not match.                                                          
[ant:jacocoReport] Execution data for class com/mkobit/libraryexample/ExampleSrc$_nonCpsDouble_closure1 does not match.        
[ant:jacocoReport] Execution data for class com/mkobit/libraryexample/ExampleSrc does not match.

jacoco_integration_tests

I think the first step is to figure out what kind of instrumentation data is output by JaCoCo and then see if that can be mapped to the existing Gradle task. If you have any other suggestions please let me now!

@mkobit
Copy link
Owner Author

mkobit commented Feb 16, 2018

Another possibility is the forked @JenkinsRule process (if it is forked) does not have instrumentation.

@markguckian
Copy link

I just got *.exec files created but no reports.
Would it be useful to provide the sourceDirectories & classDirectories values in the jacocoIntegrationTestReport task?
e.g. classDirectories = files(java.sourceSets["main"].output)

(Only just started looking at Jenkins pipeline testing/gradle so excuse my lack of knowledge!)

@mkobit
Copy link
Owner Author

mkobit commented Feb 16, 2018

Don't worry about it @markguckian , glad to have some more eyes on this. Questions will hopefully help drive some better documentation.

In the example above that I tried I did create the report task with "jacocoIntegrationTestReport"(JacocoReport::class) and sourceSets(main). I think that sets up the task dependencies, source code directories, and output classes directories, but I could be wrong. It is worth trying your proposal to see if I'm missing something. Another thing worth noting is that the main classes are not available on the integrationTest runtime classpath on purpose. I don't think that would change anything.

Changing the above example from:

    val main by java.sourceSets
    sourceSets(main)

to

    val main by java.sourceSets
    val integrationTest by java.sourceSets
    sourceSets(main)

And the report is:

jacoco_int_test

Which shows that there is at least sort of coverage for some classes.

My belief here is that JaCoCo isn't mapping the runtime compiled Groovy classes to the source code, either because Jenkins is doing something different or the interaction with Jacoco isn't right.

I think some of what needs to happen for me or whoever wants to investigate this is:

  • Determine if @JenkinsRule forks a process that isn't getting a javaagent set. I don't think it is due to what I looked at above.
  • See what is in the *.exec data, and find out if anything captured contains references to the source (specifically the com.mkobit.libraryexample.ExampleSrc class in the example). There might be some differently named class or it might not even be present at all, I have no idea.
  • Determine if there is a way to map the coverage data to the generated class. This will probably need to be handled by reaching out on the JaCoCo user's forum at https://groups.google.com/forum/#!forum/jacoco
  • Get the JacocoReport task to work with that data

I think the cloning https://github.com/mkobit/jenkins-pipeline-shared-library-example would be the best place to start. Any help here would be greatly appreciated!

@mkobit mkobit changed the title Document how to use jacoco plugin to get coverage Determine how to use jacoco plugin to get coverage for integration tests Feb 16, 2018
@mkobit
Copy link
Owner Author

mkobit commented Feb 16, 2018

Some further investigation:

  • Using example's integrationTest.exec

  • wget http://central.maven.org/maven2/org/jacoco/org.jacoco.cli/0.8.0/org.jacoco.cli-0.8.0-nodeps.jar

  • java -jar org.jacoco.cli-0.8.0-nodeps.jar execinfo integrationTest.exec | awk 'NR < 3 || /ExampleSrc/'

    [INFO] Loading exec file integrationTest.exec.
    CLASS ID         HITS/PROBES   CLASS NAME
    1c7075038cbf406d   30 of  43   com/mkobit/libraryexample/ExampleSrcSpockSpec
    58eba6c3f775908a    9 of  17   com/mkobit/libraryexample/ExampleSrc$_nonCpsDouble_closure1
    e5813609ff177775   15 of  27   com/mkobit/libraryexample/ExampleSrc
    95fc19ee2451d6a7   15 of  27   com/mkobit/libraryexample/ExampleSrc
    ```451d6a7   15 of  27   com/mkobit/libraryexample/ExampleSrc
    

But, I don't really know if that is useful. There are multiple class id in side of the report, so that could be the reason why the association isn't there. http://www.jacoco.org/jacoco/trunk/doc/classids.html might help figure this out.

@mkobit
Copy link
Owner Author

mkobit commented Feb 16, 2018

I think that is useful, and I think I'm getting closer.

Adding in class dumping:

tasks {
  "wrapper"(Wrapper::class) {
    gradleVersion = "4.4.1"
  }
  "integrationTest" {
    extensions.findByType(JacocoTaskExtension::class.java)?.apply {
      classDumpDir = file("$buildDir/jacoco/classpathdumps")
    }
  }
  "jacocoIntegrationTestReport"(JacocoReport::class) {
    reports {
      csv.setEnabled(true)
      xml.setEnabled(true)
    }
    executionData(tasks["integrationTest"])
    val main by java.sourceSets
    sourceDirectories = main.allSource
    classDirectories = fileTree("$buildDir/jacoco/classpathdumps")
  }
}

And running ./gradlew integrationTest jacocoIntegrationTestReport -s gets me:

Caused by: java.io.IOException: Error while analyzing ExampleSrc.d35369e182b13604.class.
        at org.jacoco.core.analysis.Analyzer.analyzerError(Analyzer.java:157)
        at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:129)
        at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:152)
        at org.jacoco.core.analysis.Analyzer.analyzeAll(Analyzer.java:188)
        at org.jacoco.ant.ReportTask.createBundle(ReportTask.java:570)
        at org.jacoco.ant.ReportTask.createReport(ReportTask.java:542)
        at org.jacoco.ant.ReportTask.execute(ReportTask.java:495)
        ... 63 more
Caused by: java.lang.IllegalStateException: Can't add different class with same name: com/mkobit/libraryexample/ExampleSrc
        at org.jacoco.core.analysis.CoverageBuilder.visitCoverage(CoverageBuilder.java:107)
        at org.jacoco.core.analysis.Analyzer$1.visitEnd(Analyzer.java:96)
        at org.objectweb.asm.ClassVisitor.visitEnd(ClassVisitor.java:339)
        at org.jacoco.core.internal.flow.ClassProbesAdapter.visitEnd(ClassProbesAdapter.java:98)
        at org.objectweb.asm.ClassReader.accept(ClassReader.java:702)
        at org.objectweb.asm.ClassReader.accept(ClassReader.java:500)
        at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:111)
        at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:127)
        ... 68 more

Looking at the dumped classes, there is a WorkflowScript created for each test and a class of each pipeline class in each test.

 find . -type f | grep -E 'WorkflowScript.*|evenOrOdd.*|ExampleSrc.*'
./WorkflowScript.41c8590264cdca54.class
./com/mkobit/libraryexample/ExampleSrc.4efa3fc888e78d12.class
./com/mkobit/libraryexample/ExampleSrc.d35369e182b13604.class
./com/mkobit/libraryexample/ExampleSrcSpockSpec.1c7075038cbf406d.class
./com/mkobit/libraryexample/ExampleSrc$_nonCpsDouble_closure1.58eba6c3f775908a.class
./evenOrOdd.67a9f0a3fa479d86.class
./WorkflowScript.dce4ff5df8779161.class
./WorkflowScript.1d2a368ecc6fffc0.class
./evenOrOdd.f9410339e9178dae.class
./WorkflowScript.0864c6a0b6b9e4ea.class
./WorkflowScript.89d6e909e66ff771.class
./WorkflowScript.596644e67515fe69.class

So, I think we need some way to "merge" those classes.

If I delete the duplicates of each one change the tasks block to:

tasks {
  "wrapper"(Wrapper::class) {
    gradleVersion = "4.4.1"
  }
  "integrationTest" {
    extensions.findByType(JacocoTaskExtension::class.java)?.apply {
      classDumpDir = file("$buildDir/jacoco/classpathdumps")
    }
  }
  "jacocoIntegrationTestReport"(JacocoReport::class) {
    reports {
      csv.isEnabled = true
      xml.isEnabled = true
    }
    executionData(tasks["integrationTest"])
    val main by java.sourceSets
    sourceDirectories = main.allSource
    classDirectories = fileTree("$buildDir/jacoco/classpathdumps").apply {
      include("evenOrOdd.*")
      include("doStuff.*")
      include("**/*ExampleSrc.*")
    }
  }
}

I finally get some coverage data!

screenshot from 2018-02-16 15-56-10

I think I'm really close to cracking the shell here. I still need to figure out how to handle the duplicate classes and what not. I don't think http://www.eclemma.org/jacoco/trunk/doc/offline.html will help, because these are compiled by Jenkins itself.

@markguckian
Copy link

Very promising, thanks for the hard work @mkobit

@mkobit
Copy link
Owner Author

mkobit commented Feb 16, 2018

I opened a question on the forum at https://groups.google.com/forum/#!msg/jacoco/-zTg9Bt5964/dUliK8OsAwAJ

@mkobit
Copy link
Owner Author

mkobit commented Feb 26, 2018

After getting some feedback on the forum post, I think that some work would need to be done to support getting coverage of library code. Here is a summary of what I think would need to happen based on the information I have right now:

  • The pipeline classes are compiled "basically the same" except for some constants. This seems to come from some of the internals of Jenkins pipeline.

  • Because the constants are different, different class Ids are generated but the classnames are the same. JaCoCo does not like that and the JacocoReport task fails inside of Gradle with:

      Caused by: : Error while creating report
              at org.jacoco.ant.ReportTask.execute(ReportTask.java:501)
              at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:293)
              at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
              at org.gradle.api.internal.project.ant.BasicAntBuilder.nodeCompleted(BasicAntBuilder.java:78)
              at org.gradle.internal.metaobject.BeanDynamicObject$MetaClassAdapter.invokeMethod(BeanDynamicObject.java:479)
              at org.gradle.internal.metaobject.BeanDynamicObject.tryInvokeMethod(BeanDynamicObject.java:191)
              at org.gradle.internal.metaobject.AbstractDynamicObject.invokeMethod(AbstractDynamicObject.java:160)
              at org.gradle.api.internal.project.antbuilder.AntBuilderDelegate.nodeCompleted(AntBuilderDelegate.java:118)
              at org.gradle.internal.jacoco.AbstractAntJacocoReport.invokeJacocoReport(AbstractAntJacocoReport.java:56)
              at org.gradle.internal.jacoco.AntJacocoReport$1.execute(AntJacocoReport.java:38)
              at org.gradle.internal.jacoco.AntJacocoReport$1.execute(AntJacocoReport.java:35)
              at org.gradle.internal.jacoco.AbstractAntJacocoReport$1.doCall(AbstractAntJacocoReport.java:46)
              at org.gradle.api.internal.ClosureBackedAction.execute(ClosureBackedAction.java:71)
              at org.gradle.api.internal.ClosureBackedAction.execute(ClosureBackedAction.java:53)
              at org.gradle.api.internal.project.antbuilder.DefaultIsolatedAntBuilder$2.execute(DefaultIsolatedAntBuilder.java:152)
              at org.gradle.api.internal.project.antbuilder.DefaultIsolatedAntBuilder$2.execute(DefaultIsolatedAntBuilder.java:134)
              at org.gradle.api.internal.project.antbuilder.ClassPathToClassLoaderCache.withCachedClassLoader(ClassPathToClassLoaderCache.java:134)
              at org.gradle.api.internal.project.antbuilder.DefaultIsolatedAntBuilder.execute(DefaultIsolatedAntBuilder.java:128)
              at org.gradle.internal.jacoco.AbstractAntJacocoReport.configureAntReportTask(AbstractAntJacocoReport.java:38)
              at org.gradle.internal.jacoco.AntJacocoReport.execute(AntJacocoReport.java:35)
              at org.gradle.testing.jacoco.tasks.JacocoReport.generate(JacocoReport.java:78)
              at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
              at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:46)
              at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
              at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
              at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:780)
              at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:747)
              at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:121)
              at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
              at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
              at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
              at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
              at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:110)
              at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:92)
              ... 30 more
      Caused by: java.io.IOException: Error while analyzing ExampleSrc.0711a1bac2269780.class.
              at org.jacoco.core.analysis.Analyzer.analyzerError(Analyzer.java:157)
              at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:129)
              at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:152)
              at org.jacoco.core.analysis.Analyzer.analyzeAll(Analyzer.java:188)
              at org.jacoco.ant.ReportTask.createBundle(ReportTask.java:570)
              at org.jacoco.ant.ReportTask.createReport(ReportTask.java:542)
              at org.jacoco.ant.ReportTask.execute(ReportTask.java:495)
              ... 63 more
      Caused by: java.lang.IllegalStateException: Can't add different class with same name: com/mkobit/libraryexample/ExampleSrc
              at org.jacoco.core.analysis.CoverageBuilder.visitCoverage(CoverageBuilder.java:107)
              at org.jacoco.core.analysis.Analyzer$1.visitEnd(Analyzer.java:96)
              at org.objectweb.asm.ClassVisitor.visitEnd(ClassVisitor.java:339)
              at org.jacoco.core.internal.flow.ClassProbesAdapter.visitEnd(ClassProbesAdapter.java:98)
              at org.objectweb.asm.ClassReader.accept(ClassReader.java:702)
              at org.objectweb.asm.ClassReader.accept(ClassReader.java:500)
              at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:111)
              at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:127)
              ... 68 more
    
  • This error will occur both library classes and pipeline scripts (WorkflowScript). A WorkflowScript appears to be generated for each pipeline/WorkflowJob

I think the implementation, as based on the suggestion from Marc Hoffman, will have to implement coverage merging using the JaCoCo APIs. Cloning the branch at https://github.com/mkobit/jenkins-pipeline-shared-library-example/tree/mk/coverage-investigation , running ./gradlew build, inspecting the classes in build/jacoco/classpathdumps, and trying to implement some of the suggested JaCoCo APIs (ICoverageVisitor and IClassCoverage visitor mentioned in post) on those classes and source code seems like a good starting point.

This is a bit more work than I originally hoped for with this issue, so I don't think I'll get to it anytime soon.


Side Note: OpenClover might be another option (possibly attempted with https://github.com/bmuschko/gradle-clover-plugin) but I think the same problems will be encountered.

@js-timbirkett
Copy link

js-timbirkett commented Jan 22, 2021

I have some library functions in helm.groovy and aws.groovy under vars/(nothing under src/) in my pipeline library, and using the gradle Jacoco plugin, this seemed to work for me (in build.gradle):

test {
    systemProperty "pipeline.stack.write", project.getProperty("pipeline.stack.write")
    useJUnitPlatform()
    testLogging {
        events "passed", "skipped", "failed"
    }
    jacoco {
        classDumpDir = file("$buildDir/jacoco/classpathdumps")
    }
    finalizedBy jacocoTestReport
}

jacocoTestReport {
    afterEvaluate {
        classDirectories.from = fileTree(dir: "$buildDir/jacoco/classpathdumps",
                includes: [
                        'helm.*',
                        'aws.*'
                ]
        )
    }
    reports {
        csv.enabled false
        xml {
            enabled true
            destination file("${buildDir}/test-results/jacoco.xml")
        }
        html.destination file("${buildDir}/reports/jacoco")
    }
}

(notice that the list of classes is filtered with includes:)

This might help others get a bit further with some tweaking.

@mahmoud-ashi
Copy link

@js-timbirkett, can you please give full example of your build.gradle script and the command you run to run the tests and collect the coverage? In my case, I have some scripts in vars and in src but I care more about the coverage of the vars scripts. I tried adding the 2 tasks as you have and ran a gradle test with IntelliJ with jacoco coverage but end up getting tons of exceptions like following:

> Task :compileJava NO-SOURCE
> Task :compileGroovy UP-TO-DATE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE
> Task :compileTestJava NO-SOURCE
> Task :compileTestGroovy UP-TO-DATE
> Task :processTestResources NO-SOURCE
> Task :testClasses UP-TO-DATE
> Task :test
Exception in thread "main" java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:513)
	at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:525)
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.jacoco.agent.rt.internal_f3994fa.core.runtime.InjectedClassRuntime$Lookup.defineClass(InjectedClassRuntime.java:134)
	at org.jacoco.agent.rt.internal_f3994fa.core.runtime.InjectedClassRuntime.startup(InjectedClassRuntime.java:54)
	at org.jacoco.agent.rt.internal_f3994fa.PreMain.premain(PreMain.java:53)
	... 6 more
Caused by: java.lang.LinkageError: loader 'bootstrap' attempted duplicate class definition for java.lang.$JaCoCo. (java.lang.$JaCoCo is in module java.base of loader 'bootstrap')
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.System$2.defineClass(System.java:2131)
FATAL ERROR in native method: processing of -javaagent failed, processJavaStart failed
	at java.base/java.lang.invoke.MethodHandles$Lookup.defineClass(MethodHandles.java:962)
	... 13 more
*** java.lang.instrument ASSERTION FAILED ***: "result" with message agent load/premain call failed at src/java.instrument/share/native/libinstrument/JPLISAgent.c line: 422
Exception in thread "main" java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:513)
	at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:525)
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.jacoco.agent.rt.internal_f3994fa.core.runtime.InjectedClassRuntime$Lookup.defineClass(InjectedClassRuntime.java:134)
	at org.jacoco.agent.rt.internal_f3994fa.core.runtime.InjectedClassRuntime.startup(InjectedClassRuntime.java:54)
	at org.jacoco.agent.rt.internal_f3994fa.PreMain.premain(PreMain.java:53)
	... 6 more

Appreciate your help!

dblock added a commit to dblock/opensearch-build that referenced this issue Nov 17, 2021
dblock added a commit to dblock/opensearch-build that referenced this issue Nov 17, 2021
dblock added a commit to opensearch-project/opensearch-build that referenced this issue Nov 17, 2021
* Added test coverage for Groovy code.

Signed-off-by: dblock <dblock@amazon.com>

* Enable coverage for JenkinsPipelineUnit tests.

See mkobit/jenkins-pipeline-shared-libraries-gradle-plugin#32 and jenkinsci/JenkinsPipelineUnit#103.

Signed-off-by: dblock <dblock@amazon.com>

* Remove base Manifest class that generates duplicate execution dump.

Signed-off-by: dblock <dblock@amazon.com>
@deporcali
Copy link

@mkobit based in your research and comments I extended it to something that works really good for me. I got around the duplicated classes error by creating several Jacoco xml reports and then merging them. For this SonarQube was really useful since it accepts several Jacoco xml reports. See jenkinsci/JenkinsPipelineUnit#103 (comment) for more information

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants