如何配置 build.gradle 使用 Junit5 和 Jacoco 进行测试覆盖
How to configure build.gradle using Junit5 and Jacoco for test coverage
我正在尝试配置 build.gradle 文件,使其同时支持 Junit 5 和 Jacoco。我之前使用过 useJunitPlatform,但它会产生另一个错误。我也尝试了其他一些方法,但是 none 可以成功生成 Jacoco 报告。然而,这个配置成功地为我生成了 Jacoco 报告,但它也给了我一个例外。下面是我的 build.gradle 文件。
plugins {
// Build "fat" jars for deployment
id 'com.github.johnrengelman.shadow' version '5.2.0'
// Apply the java plugin to add support for Java
id 'java'
// Apply the application plugin to add support for building a CLI application.
id 'application'
// Deploy directly to heroku without using Git
id "com.heroku.sdk.heroku-gradle" version "1.0.4"
// Lombok provides shorthand for repetitive Java tasks
id "io.freefair.lombok" version "4.1.6"
// Spotless to format code easily
id "com.diffplug.gradle.spotless" version "3.27.1"
// Jacoco test coverage
id 'jacoco'
}
repositories {
// Use jcenter for resolving dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
dependencies {
// Simple HTTP framework - http://sparkjava.com/
implementation 'com.sparkjava:spark-core:2.9.1'
// Basic logging support; used by Spark
implementation "org.slf4j:slf4j-simple:1.7.25"
// Jackson to serialize/deserialize JSON
implementation 'com.fasterxml.jackson.core:jackson-databind:2.10.2'
// Use JUnit Jupiter API for testing.
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
testImplementation 'org.junit.platform:junit-platform-launcher:1.5.2'
// Use JUnit Jupiter Engine for testing.
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.5.2'
// Use dagger for dependency injection
implementation 'com.google.dagger:dagger:2.26'
annotationProcessor 'com.google.dagger:dagger-compiler:2.26'
// Annotations such as Nullable
implementation 'com.google.code.findbugs:annotations:3.0.1'
// Force JRE Guava to work around issues with Truth
testImplementation "com.google.guava:guava:28.2-jre"
// Fluent assertions for testing
testImplementation 'com.google.truth:truth:1.0.1'
// MongoDB client
implementation 'org.mongodb:mongodb-driver:3.12.1'
}
application {
// Define the main class for the application.
mainClassName = 'edu.northeastern.cs5500.delivery.App'
}
jacoco {
toolVersion = "0.8.5"
reportsDir = file("$buildDir/customJacocoReportDir")
}
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
html.destination file("${buildDir}/jacocoHtml")
}
afterEvaluate {
classDirectories.from = files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
'**/model/**',
'**/view/**',
'**/utils/**',
'**/service/**'
])
})
}
doLast {
println "file://$buildDir/jacocoHtml/index.html"
}
}
test {
// Use junit platform for unit tests
useJUnit()
finalizedBy jacocoTestReport
}
// Heroku will run the 'stage' task on deployment via git
task stage(dependsOn: ['clean', 'shadowJar'])
shadowJar.mustRunAfter clean
// Force all builds to be clean builds due to Dagger problems
build.mustRunAfter clean
build.dependsOn += 'clean'
run.mustRunAfter clean
run.dependsOn += 'clean'
// Target Java 1.11 - make sure system.properties matches this as well
sourceCompatibility = 1.11
targetCompatibility = 1.11
sourceSets {
main {
java {
srcDirs 'src/main/java'
srcDirs 'build/generated/sources/annotationProcessor/java/main'
}
}
test {
java {
srcDirs 'src/test/java'
srcDirs 'build/generated/sources/annotationProcessor/java/test'
}
}
}
spotless {
format 'misc', {
target '**/*.gradle', '**/*.md', '**/.gitignore'
targetExclude 'build/**'
trimTrailingWhitespace()
indentWithSpaces()
endWithNewline()
paddedCell()
}
java {
targetExclude 'build/**'
googleJavaFormat().aosp()
}
}
我每次构建时出现的错误如下图
java.lang.instrument.IllegalClassFormatException: Error while instrumenting sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo.
at org.jacoco.agent.rt.internal_43f5073.CoverageTransformer.transform(CoverageTransformer.java:94)
at java.instrument/java.lang.instrument.ClassFileTransformer.transform(ClassFileTransformer.java:246)
at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:563)
at java.base/java.lang.ClassLoader.defineClass2(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1108)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:183)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:784)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(BuiltinClassLoader.java:705)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClass(BuiltinClassLoader.java:586)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:634)
at java.base/java.lang.Class.forName(Class.java:546)
at java.base/java.util.ServiceLoader.loadProvider(ServiceLoader.java:854)
at java.base/java.util.ServiceLoader$ModuleServicesLookupIterator.hasNext(ServiceLoader.java:1078)
at java.base/java.util.ServiceLoader.hasNext(ServiceLoader.java:1301)
at java.base/java.util.ServiceLoader.hasNext(ServiceLoader.java:1386)
at java.base/sun.util.cldr.CLDRLocaleProviderAdapter.run(CLDRLocaleProviderAdapter.java:89)
at java.base/sun.util.cldr.CLDRLocaleProviderAdapter.run(CLDRLocaleProviderAdapter.java:86)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:554)
at java.base/sun.util.cldr.CLDRLocaleProviderAdapter.<init>(CLDRLocaleProviderAdapter.java:86)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
at java.base/sun.util.locale.provider.LocaleProviderAdapter.forType(LocaleProviderAdapter.java:188)
at java.base/sun.util.locale.provider.LocaleProviderAdapter.findAdapter(LocaleProviderAdapter.java:287)
at java.base/sun.util.locale.provider.LocaleProviderAdapter.getAdapter(LocaleProviderAdapter.java:258)
at java.base/java.util.Calendar.createCalendar(Calendar.java:1693)
at java.base/java.util.Calendar.getInstance(Calendar.java:1661)
at java.base/java.text.SimpleDateFormat.initializeCalendar(SimpleDateFormat.java:677)
at java.base/java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:621)
at java.base/java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:600)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.getLastResortErrorLogFile(SystemApplicationClassLoaderWorker.java:162)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:111)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.io.IOException: Error while instrumenting sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo.
at org.jacoco.agent.rt.internal_43f5073.core.instr.Instrumenter.instrumentError(Instrumenter.java:159)
at org.jacoco.agent.rt.internal_43f5073.core.instr.Instrumenter.instrument(Instrumenter.java:109)
at org.jacoco.agent.rt.internal_43f5073.CoverageTransformer.transform(CoverageTransformer.java:92)
... 37 more
Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 59
at org.jacoco.agent.rt.internal_43f5073.asm.ClassReader.<init>(ClassReader.java:195)
at org.jacoco.agent.rt.internal_43f5073.asm.ClassReader.<init>(ClassReader.java:176)
at org.jacoco.agent.rt.internal_43f5073.asm.ClassReader.<init>(ClassReader.java:162)
at org.jacoco.agent.rt.internal_43f5073.core.internal.instr.InstrSupport.classReaderFor(InstrSupport.java:280)
at org.jacoco.agent.rt.internal_43f5073.core.instr.Instrumenter.instrument(Instrumenter.java:75)
at org.jacoco.agent.rt.internal_43f5073.core.instr.Instrumenter.instrument(Instrumenter.java:107)
... 38 more
感谢您的帮助!
根据您的错误信息
Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 59
并根据 https://en.wikipedia.org/wiki/Java_class_file
你正在使用 Java 15.
根据https://www.jacoco.org/jacoco/trunk/doc/changes.html
在 JaCoCo 版本 0.8.6
中添加了对 Java 15 的支持
所以要么您不需要 Java 15 并且可以使用更早的版本,例如 11 (LTS),要么您需要更改
jacoco {
toolVersion = "0.8.5"
在
jacoco {
toolVersion = "0.8.6"
对我来说,问题出在 com.github.johnrengelman.shadow 版本上,升级到 6.1.0 版本后,问题解决了
我正在尝试配置 build.gradle 文件,使其同时支持 Junit 5 和 Jacoco。我之前使用过 useJunitPlatform,但它会产生另一个错误。我也尝试了其他一些方法,但是 none 可以成功生成 Jacoco 报告。然而,这个配置成功地为我生成了 Jacoco 报告,但它也给了我一个例外。下面是我的 build.gradle 文件。
plugins {
// Build "fat" jars for deployment
id 'com.github.johnrengelman.shadow' version '5.2.0'
// Apply the java plugin to add support for Java
id 'java'
// Apply the application plugin to add support for building a CLI application.
id 'application'
// Deploy directly to heroku without using Git
id "com.heroku.sdk.heroku-gradle" version "1.0.4"
// Lombok provides shorthand for repetitive Java tasks
id "io.freefair.lombok" version "4.1.6"
// Spotless to format code easily
id "com.diffplug.gradle.spotless" version "3.27.1"
// Jacoco test coverage
id 'jacoco'
}
repositories {
// Use jcenter for resolving dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
dependencies {
// Simple HTTP framework - http://sparkjava.com/
implementation 'com.sparkjava:spark-core:2.9.1'
// Basic logging support; used by Spark
implementation "org.slf4j:slf4j-simple:1.7.25"
// Jackson to serialize/deserialize JSON
implementation 'com.fasterxml.jackson.core:jackson-databind:2.10.2'
// Use JUnit Jupiter API for testing.
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
testImplementation 'org.junit.platform:junit-platform-launcher:1.5.2'
// Use JUnit Jupiter Engine for testing.
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.5.2'
// Use dagger for dependency injection
implementation 'com.google.dagger:dagger:2.26'
annotationProcessor 'com.google.dagger:dagger-compiler:2.26'
// Annotations such as Nullable
implementation 'com.google.code.findbugs:annotations:3.0.1'
// Force JRE Guava to work around issues with Truth
testImplementation "com.google.guava:guava:28.2-jre"
// Fluent assertions for testing
testImplementation 'com.google.truth:truth:1.0.1'
// MongoDB client
implementation 'org.mongodb:mongodb-driver:3.12.1'
}
application {
// Define the main class for the application.
mainClassName = 'edu.northeastern.cs5500.delivery.App'
}
jacoco {
toolVersion = "0.8.5"
reportsDir = file("$buildDir/customJacocoReportDir")
}
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
html.destination file("${buildDir}/jacocoHtml")
}
afterEvaluate {
classDirectories.from = files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
'**/model/**',
'**/view/**',
'**/utils/**',
'**/service/**'
])
})
}
doLast {
println "file://$buildDir/jacocoHtml/index.html"
}
}
test {
// Use junit platform for unit tests
useJUnit()
finalizedBy jacocoTestReport
}
// Heroku will run the 'stage' task on deployment via git
task stage(dependsOn: ['clean', 'shadowJar'])
shadowJar.mustRunAfter clean
// Force all builds to be clean builds due to Dagger problems
build.mustRunAfter clean
build.dependsOn += 'clean'
run.mustRunAfter clean
run.dependsOn += 'clean'
// Target Java 1.11 - make sure system.properties matches this as well
sourceCompatibility = 1.11
targetCompatibility = 1.11
sourceSets {
main {
java {
srcDirs 'src/main/java'
srcDirs 'build/generated/sources/annotationProcessor/java/main'
}
}
test {
java {
srcDirs 'src/test/java'
srcDirs 'build/generated/sources/annotationProcessor/java/test'
}
}
}
spotless {
format 'misc', {
target '**/*.gradle', '**/*.md', '**/.gitignore'
targetExclude 'build/**'
trimTrailingWhitespace()
indentWithSpaces()
endWithNewline()
paddedCell()
}
java {
targetExclude 'build/**'
googleJavaFormat().aosp()
}
}
我每次构建时出现的错误如下图
java.lang.instrument.IllegalClassFormatException: Error while instrumenting sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo.
at org.jacoco.agent.rt.internal_43f5073.CoverageTransformer.transform(CoverageTransformer.java:94)
at java.instrument/java.lang.instrument.ClassFileTransformer.transform(ClassFileTransformer.java:246)
at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:563)
at java.base/java.lang.ClassLoader.defineClass2(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1108)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:183)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:784)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(BuiltinClassLoader.java:705)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClass(BuiltinClassLoader.java:586)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:634)
at java.base/java.lang.Class.forName(Class.java:546)
at java.base/java.util.ServiceLoader.loadProvider(ServiceLoader.java:854)
at java.base/java.util.ServiceLoader$ModuleServicesLookupIterator.hasNext(ServiceLoader.java:1078)
at java.base/java.util.ServiceLoader.hasNext(ServiceLoader.java:1301)
at java.base/java.util.ServiceLoader.hasNext(ServiceLoader.java:1386)
at java.base/sun.util.cldr.CLDRLocaleProviderAdapter.run(CLDRLocaleProviderAdapter.java:89)
at java.base/sun.util.cldr.CLDRLocaleProviderAdapter.run(CLDRLocaleProviderAdapter.java:86)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:554)
at java.base/sun.util.cldr.CLDRLocaleProviderAdapter.<init>(CLDRLocaleProviderAdapter.java:86)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
at java.base/sun.util.locale.provider.LocaleProviderAdapter.forType(LocaleProviderAdapter.java:188)
at java.base/sun.util.locale.provider.LocaleProviderAdapter.findAdapter(LocaleProviderAdapter.java:287)
at java.base/sun.util.locale.provider.LocaleProviderAdapter.getAdapter(LocaleProviderAdapter.java:258)
at java.base/java.util.Calendar.createCalendar(Calendar.java:1693)
at java.base/java.util.Calendar.getInstance(Calendar.java:1661)
at java.base/java.text.SimpleDateFormat.initializeCalendar(SimpleDateFormat.java:677)
at java.base/java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:621)
at java.base/java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:600)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.getLastResortErrorLogFile(SystemApplicationClassLoaderWorker.java:162)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:111)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.io.IOException: Error while instrumenting sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo.
at org.jacoco.agent.rt.internal_43f5073.core.instr.Instrumenter.instrumentError(Instrumenter.java:159)
at org.jacoco.agent.rt.internal_43f5073.core.instr.Instrumenter.instrument(Instrumenter.java:109)
at org.jacoco.agent.rt.internal_43f5073.CoverageTransformer.transform(CoverageTransformer.java:92)
... 37 more
Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 59
at org.jacoco.agent.rt.internal_43f5073.asm.ClassReader.<init>(ClassReader.java:195)
at org.jacoco.agent.rt.internal_43f5073.asm.ClassReader.<init>(ClassReader.java:176)
at org.jacoco.agent.rt.internal_43f5073.asm.ClassReader.<init>(ClassReader.java:162)
at org.jacoco.agent.rt.internal_43f5073.core.internal.instr.InstrSupport.classReaderFor(InstrSupport.java:280)
at org.jacoco.agent.rt.internal_43f5073.core.instr.Instrumenter.instrument(Instrumenter.java:75)
at org.jacoco.agent.rt.internal_43f5073.core.instr.Instrumenter.instrument(Instrumenter.java:107)
... 38 more
感谢您的帮助!
根据您的错误信息
Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 59
并根据 https://en.wikipedia.org/wiki/Java_class_file 你正在使用 Java 15.
根据https://www.jacoco.org/jacoco/trunk/doc/changes.html 在 JaCoCo 版本 0.8.6
中添加了对 Java 15 的支持所以要么您不需要 Java 15 并且可以使用更早的版本,例如 11 (LTS),要么您需要更改
jacoco {
toolVersion = "0.8.5"
在
jacoco {
toolVersion = "0.8.6"
对我来说,问题出在 com.github.johnrengelman.shadow 版本上,升级到 6.1.0 版本后,问题解决了