Caleb Cushing
10/09/2024, 6:40 PMGradleRunner run code to be reported in coverage? or is there a way to make a ProjectBuilder project execute a task?Vampire
10/10/2024, 6:56 AMephemient
10/10/2024, 6:57 AMVampire
10/10/2024, 9:32 AMjacocoAgentJarDependency
• To that I add org.jacoco:org.jacoco.agent:runtime as dependency
• I have a resolvable configuration named jacocoAgentJar that extends from the other
• For the test task that runs these functional tests
◦ I get val jacocoDestfile = the<JacocoTaskExtension>().destinationFile!!
◦ To prevent the strings becoming build cache inputs I do not use systemProperty, but a jvmArgumentProvider to set
▪︎ "-DjacocoAgentJar=${jacocoAgentJar.singleFile.absolutePath}"
▪︎ "-DjacocoDestfile=${jacocoDestfile.absolutePath}"
◦ As part of some quirk-work-arounds I also add
doLast {
// wait for the read lock on the file, otherwise the daemon might still
// have the write lock and Gradle complains that it cannot snapshot
// the file as output of this task and as input of the report task
FileChannel.open(jacocoDestfile.toPath(), READ).use {
it.lock(0, Long.MAX_VALUE, true).release()
}
}
• In my base test class from which all functional tests inherit
◦ I get
▪︎ def jacocoAgentJar = System.getProperty('jacocoAgentJar').replace($/\/$, $/\\/$)
▪︎ def jacocoDestfile = System.getProperty('jacocoDestfile').replace($/\/$, $/\\/$)
◦ write to the gradle.properties of the test project
▪︎ org.gradle.jvmargs = -javaagent:$jacocoAgentJar=destfile=$jacocoDestfile,append=true,dumponexit=false,jmx=true
◦ configure the GradleRunner with
.withPluginClasspath()
.with { it.withPluginClasspath(it.pluginClasspath + new File(jacocoAgentJar)) }
◦ and finally write to the settings.gradle.kts of the test project
import java.lang.management.ManagementFactory
import javax.management.JMX.newMBeanProxy
import javax.management.ObjectName
import org.jacoco.agent.rt.IAgent
abstract class JacocoDumper : BuildService<BuildServiceParameters.None>, AutoCloseable {
override fun close() {
val mBeanServer = ManagementFactory.getPlatformMBeanServer()
val jacoco = ObjectName.getInstance("org.jacoco:type=Runtime")
if (mBeanServer.isRegistered(jacoco)) {
newMBeanProxy(mBeanServer, jacoco, IAgent::class.java).dump(true)
}
}
}
val jacocoDumper = gradle.sharedServices.registerIfAbsent("jacocoDumper", JacocoDumper::class) {}
jacocoDumper.get()
gradle.allprojects {
tasks.configureEach {
usesService(jacocoDumper)
}
}
All this together turns out to work as expected for me so far.
I told you it is not trivial to get it set up right. 🙂Caleb Cushing
10/10/2024, 1:16 PMVampire
10/10/2024, 1:22 PMVampire
10/10/2024, 1:24 PMCaleb Cushing
10/10/2024, 1:57 PMCaleb Cushing
10/10/2024, 1:57 PMVampire
10/10/2024, 1:57 PM