Following a few blog posts I tried to create a separate source folder for integration testing in gradle. I wanted also to add some additinal (arquillian) dependencies to my integrationTest task, but the integrationTestCompile seems to be ignored and I get a compilation error with the additional dependecy not resolved. When I change the dependecy to testCompile it works fine. Why is that so and how to change it? My simple test class:
//compilation fails with [Static type checking] - The variable [ArquillianSputnik] is undeclared
#TypeChecked
#RunWith(ArquillianSputnik)
class TestSpec extends Specification {
}
and gradle.build:
apply plugin: 'groovy'
apply plugin: 'war'
war.dependsOn 'native2ascii'
task native2ascii << {
ant.delete() {
fileset(dir: "${processResources.destinationDir}") {
include(name: '*.properties')
}
}
ant.native2ascii(src: 'src/main/resources/',
dest: "${processResources.destinationDir}",
includes: '**/*.properties',
encoding: 'UTF-8')
}
repositories {
mavenCentral()
maven {
url 'http://repository.jboss.org/nexus/content/groups/public'
}
mavenLocal()
}
sourceSets.main.java.srcDirs = []
sourceSets.main.groovy.srcDirs += ["src/main/java"]
sourceSets {
integrationTest {
groovy.srcDir file('src/integration-test/groovy')
resources.srcDir file('src/integration-test/resources')
compileClasspath = sourceSets.main.output + configurations.testCompile
runtimeClasspath = output + compileClasspath + configurations.testRuntime
}
}
dependencies {
//(...) non-test dependencies cut out for clarity
testCompile 'org.spockframework:spock-core:0.7-groovy-2.0'
testCompile 'cglib:cglib-nodep:2.2.2'
testCompile 'org.objenesis:objenesis:1.2'
//when integrationTestCompile is changed to testCompile the compilation works and the test is executed
integrationTestCompile 'org.jboss.arquillian.spock:arquillian-spock-container:1.0.0.Beta3'
integrationTestCompile 'org.jboss.arquillian.graphene:graphene-webdriver:2.0.3.Final'
integrationTestCompile 'org.jboss.as:jboss-as-arquillian-container-managed:7.2.0.Final'
}
task integrationTest(type: Test, dependsOn: 'test') {
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
}
check.dependsOn 'integrationTest'
First, you want to add to the compile and runtime classpaths rather than replace them. This really just means using the += operator rather than the = one. Additionally, you really only want to add the other sourcesets output, we'll deal with configurations separately.
compileClasspath += sourcesets.main.output + sourcesets.test.output
runtimeClasspath += sourcesets.main.output + sourcesets.test.output
Next, we'll want to configure our integration test configurations. Usually, this just means making them extend the test and compile ones so that they contain all those dependencies as well.
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}
Related
I have multimodule gradle project. When I add com.google.protobuf to build.gradle - it affects to testIntegration module.
Without plugin:
With plugin:
And the real problem is - when I run Jenkins build job - it freezes on testIntegration. Without plugin - all works fine.
gradle.build
apply plugin:'com.google.protobuf'
def grpcVersion = '1.30.0'
dependencies {
...
implementation "io.grpc:grpc-netty:${grpcVersion}"
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
implementation "io.grpc:grpc-stub:${grpcVersion}"
...
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.8.0"
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.30.0'
}
}
generateProtoTasks {
all()*.plugins {
grpc {}
}
}
}
main-gradle.build
...
subprojects {
configurations {
compileOnly {
extendsFrom annotationProcessor
}
testIntegrationImplementation.extendsFrom(testImplementation)
testIntegrationRuntimeOnly.extendsFrom(testRuntimeOnly)
}
sourceSets {
testIntegration {
compileClasspath += sourceSets.main.output
runtimeClasspath += sourceSets.main.output
}
}
...
In my Java (Gradle-based) project, I have the default test task and custom defined integrationTest task. My build.gradle looks following
plugins {
id 'de.jansauer.printcoverage' version '2.0.0'
}
apply plugin: 'idea'
apply plugin: 'java'
apply plugin: 'jacoco'
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
sourceSets {
integration {
java.srcDir "$projectDir/src/integration/java"
resources.srcDir "$projectDir/src/integration/resources"
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
}
}
configurations {
integrationImplementation.extendsFrom testImplementation
integrationImplementation.canBeResolved true
integrationRuntimeOnly.extendsFrom testRuntimeOnly
integrationRuntimeOnly.canBeResolved true
}
task integrationTest(type: Test) {
description = 'Runs the integration tests.'
group = 'verification'
testClassesDirs = sourceSets.integration.output.classesDirs
classpath = sourceSets.integration.runtimeClasspath
outputs.upToDateWhen { false }
useJUnitPlatform()
}
idea {
module {
testSourceDirs += sourceSets.integration.java.srcDirs
testResourceDirs += sourceSets.integration.resources.srcDirs
}
}
check.dependsOn integrationTest
repositories {
mavenCentral()
}
dependencies {
testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.8.2'
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.8.2'
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '5.8.2'
testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.4.6'
testImplementation group: 'org.mockito', name: 'mockito-junit-jupiter', version: '3.4.6'
testImplementation group: 'org.mockito', name: 'mockito-inline', version: '3.4.6'
}
test {
useJUnitPlatform()
finalizedBy jacocoTestCoverageVerification, printCoverage
}
jacocoTestReport {
reports.xml.enabled true
}
jacocoTestCoverageVerification {
violationRules {
rule {
limit {
minimum = 1.0
}
}
}
}
In general, it works fine, but there is a problem. Sometimes there are places in code that are really difficult to unit-test, and are great for integration tests. However, JaCoCo counts only coverage in unit tests. I could place finalizedBy jacocoTestCoverageVerification, printCoverage in the integrationTest task, but then I'd have two separate coverages.
My goal is to have one common coverage from both test configuration. I tried changing finalizedBy to dependsOn (with adequate logic change), but then I had no coverage at all. I don't know if it's even possible tbh, but I'm guessing it is.
I'm developing a gradle-multiple-project java application, code works well with lombok in intellij (getter, setter method is visible), but when I run gradle build then fail, get the message:
~/EventStormingWorkShop/sources/coffeeshop/coffee-domain/src/main/java/solid/humank/port/adapter/OrderReceiverAdapter.java:41: error: cannot find symbol
String orderString= mapper.writeValueAsString(orderCreatedEvent.getDetail());
^
symbol: method getDetail()
location: variable orderCreatedEvent of type OrderCreatedEvent
Current environment:
Intellij : 2019.2.3
Gradle : 5.6.2
JDK : GraalVM 19.2.0 (compatible with JDK 1.8_0222)
lombok : 1.8.10
I had checked the lombok dependencies declaration in build.gradle.
compileOnly "org.projectlombok:lombok:${lombokVersion}"
annotationProcessor "org.projectlombok:lombok:${lombokVersion}"
testCompileOnly "org.projectlombok:lombok:${lombokVersion}"
testAnnotationProcessor "org.projectlombok:lombok:${lombokVersion}"
at compile time everything wen well.
Here is the build.gradle from my rootProject
buildscript {
ext {
quarkusJunitVersion = '0.22.0'
restAssuredVersion = '3.3.0'
cucumberVersion = '4.7.1'
lombokVersion = '1.18.10'
quarkusVersion = '0.23.1'
awsJavaVersion = '1.11.631'
awsVersion = '2.5.29'
}
}
apply from: file("${rootDir}/gradle/project.gradle")
List testCompilePackage = ["io.quarkus:quarkus-junit5:${quarkusJunitVersion}", "io.rest-assured:rest-assured:${restAssuredVersion}"]
List testImplementPackage = ["io.cucumber:cucumber-java8:${cucumberVersion}", "io.cucumber:cucumber-junit:${cucumberVersion}"]
List implementationPackage = ["io.quarkus:quarkus-resteasy",
"com.amazonaws:aws-java-sdk-lambda",
"com.amazonaws:aws-java-sdk-dynamodb",
"com.amazonaws:aws-lambda-java-core",
"com.amazonaws:aws-lambda-java-events",
"com.amazonaws:aws-java-sdk-events"]
subprojects { dir ->
repositories {
mavenCentral()
}
dependencies {
// Lombok Support
compileOnly "org.projectlombok:lombok:${lombokVersion}"
annotationProcessor "org.projectlombok:lombok:${lombokVersion}"
testCompileOnly "org.projectlombok:lombok:${lombokVersion}"
testAnnotationProcessor "org.projectlombok:lombok:${lombokVersion}"
// quarkus test
testCompile testCompilePackage
// cucumber test
testImplementation testImplementPackage
// quarkus
compile group: 'io.quarkus', name: 'quarkus-gradle-plugin', version: "${quarkusVersion}", ext: 'pom'
implementation enforcedPlatform("io.quarkus:quarkus-bom:${quarkusVersion}")
implementation platform("com.amazonaws:aws-java-sdk-bom:${awsJavaVersion}")
implementation platform("software.amazon.awssdk:bom:${awsVersion}")
implementation implementationPackage
}
if (dir.name.endsWith("-domain")) {
dependencies {
implementation project(":ddd-commons")
}
}
if (dir.name.endsWith("-application")) {
String modName = dir.name.substring(0, dir.name.lastIndexOf("-application"))
dependencies {
implementation project(":ddd-commons"), project(":${modName}-domain")
}
}
if (dir.name.endsWith("-web")) {
String modName = dir.name.substring(0, dir.name.lastIndexOf("-web"))
dependencies {
implementation project(":ddd-commons"), project(":${modName}-domain"), project(":${modName}-application")
}
}
}
The build.gradle will apply a project.gradle file
project.gradle:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'io.quarkus:quarkus-gradle-plugin:0.23.1'
}
}
defaultTasks 'clean', 'build'
apply plugin: 'idea'
subprojects {
apply plugin: 'java'
apply plugin: io.quarkus.gradle.QuarkusPlugin
group 'solid.humank.coffeeshop'
version '1.0'
sourceCompatibility = 1.8
targetCompatibility = 1.8
idea.module.inheritOutputDirs = true
dependencies{
compileOnly "org.projectlombok:lombok:1.18.10"
annotationProcessor "org.projectlombok:lombok:1.18.10"
testCompileOnly "org.projectlombok:lombok:1.18.10"
testAnnotationProcessor "org.projectlombok:lombok:1.18.10"
}
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
options.deprecation = true
options.compilerArgs += ['-Xlint:none', '-proc:none', '-nowarn']
}
repositories {
mavenCentral()
mavenLocal()
}
buildDir = "${rootDir}/build/${rootDir.relativePath(projectDir)}"
tasks.named('test') {
useJUnitPlatform()
failFast = true
testLogging.showStandardStreams = true
testLogging.exceptionFormat 'full'
}
tasks.named('jar') {
// put parent name in final jar name, to resolve collision of child projects with same name under different parents
if (parent.depth > 0) {
archiveBaseName = "${parent.name}-${archiveBaseName.get()}"
}
}
afterEvaluate {
def buildTime = new Date()
tasks.withType(Jar) {
String ClassPathString = ''
configurations.runtime.each { ClassPathString += " lib\\" + it.name }
manifest {
attributes 'Implementation-Title': project.name,
'Implementation-Version': project.version,
'Created-By': "${System.getProperty('java.version')} (${System.getProperty('java.vendor')})",
'Built-With': "gradle-${project.gradle.gradleVersion}, groovy-${GroovySystem.version}",
'Built-By': System.getProperty('user.name'),
'Built-On': "${InetAddress.localHost.hostName}/${InetAddress.localHost.hostAddress}",
'Build-Time': buildTime.format('yyyy/MM/dd HH:mm:ss'),
'Class-Path': ClassPathString
}
}
}
}
Besides, there is the settings.gradle to include sub projects
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == 'io.quarkus') {
useModule("io.quarkus:quarkus-gradle-plugin:0.23.1")
}
}
}
}
rootProject.name = 'coffeeshop'
include 'ddd-commons'
include 'inventory-domain'
include 'inventory-application'
include 'inventory-web'
include 'coffee-application'
include 'coffee-domain'
include 'coffee-web'
include 'orders-application'
include 'orders-domain'
include 'orders-web'
I expect these settings could run gradle build well, but faced seems lombok annotation processer not worked issue in gradle runtime.
Because your project.gradle has '-proc:none'
I have gradle file configured as follows. In IDE, it doesn't resolve any of JUnit dependencies. Not sure what's wrong. I could see libraries added in the module. But imports still appear as unresolved in test files.
I tried with Eclipse and it worked fine. It's happening only with IntelliJ. Below is the snippet from my gradle file.
sourceSets {
integrationTest {
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
java {
srcDirs = ['test_dir1', 'test_dir2']
}
resources {
srcDirs = ['test_dir1', 'test_dir2']
}
}
}
configurations {
integrationTestCompile.extendsFrom(testCompile)
integrationTestRuntime.extendsFrom(testRuntime)
}
dependencies {
integrationTestCompile group: 'junit', name: 'junit', version: '4.12'
integrationTestCompile group: 'org.mockito', name: 'mockito-all', version: '1.9.5'
integrationTestCompile group: 'org.powermock', name: 'powermock-mockito-release-full', version: '1.6.4'
}
task integrationTest(type: Test) {
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
if(project.hasProperty("directoryFilter")) {
include project.getProperty("directoryFilter")
}
}
idea {
module {
sourceDirs += file('src')
testSourceDirs += file('test')
testSourceDirs += file('test_dir1')
testSourceDirs += file('test_dir2')
}
}
Figured out the issue. It's the version of Powermock against the version of JUnit. Seems IntelliJ doesn't like those two versions work with each other. Degrading Junit to 4.11 and Powermock to 1.5.5 did work for me.
With a "normal" JavaExec gradle task such as,
task('integrationTest',
type: JavaExec,
moreConf...) {
// Stuff
}
you can extends inherit compile- and runtime configurations like so,
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}
But, how do you do this with a task defined through Groovy? I.e.
def integrationTestTask = project.task(['type': JavaExec], 'integrationTest') {
stuff
}
I am writing a plugin to reduce some repeated code.
By adding the prerequisite sourceSets integrationTestCompile and ìntegrationTestRuntime` will be created and available to set,
project.task(['type': JavaExec], 'integrationTest') {
project.sourceSets {
integrationTest {
java {
// set stuff....
}
}
}
project.configurations {
// These two (integrationTestCompile/integrationTestRuntime) get created by the sourceSets block
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}
// stuff
}