From 2f53c5fb3e0fa3cc0de5be3d026b4c48e42166bc Mon Sep 17 00:00:00 2001 From: Guillaume Le Floch Date: Fri, 11 Feb 2022 10:39:01 +0100 Subject: [PATCH] Introduce integration test source set for gradle based project --- .../java/io/quarkus/gradle/QuarkusPlugin.java | 35 ++++++++++++++++-- docs/src/main/asciidoc/gradle-tooling.adoc | 12 +++++++ .../it-test-basic-project/build.gradle | 36 +++++++++++++++++++ .../it-test-basic-project/gradle.properties | 2 ++ .../it-test-basic-project/settings.gradle | 18 ++++++++++ .../java/org/acme/ExampleResourceIT.java | 12 +++++++ .../main/java/org/acme/ExampleResource.java | 17 +++++++++ .../src/main/resources/application.properties | 1 + .../java/org/acme/ExampleResourceTest.java | 20 +++++++++++ .../src/test/resources/application.properties | 0 .../gradle/IntegrationTestBuildTest.java | 22 ++++++++++++ .../gradle/MultiSourceProjectTest.java | 1 - .../test/junit/IntegrationTestUtil.java | 2 +- 13 files changed, 174 insertions(+), 4 deletions(-) create mode 100644 integration-tests/gradle/src/main/resources/it-test-basic-project/build.gradle create mode 100644 integration-tests/gradle/src/main/resources/it-test-basic-project/gradle.properties create mode 100644 integration-tests/gradle/src/main/resources/it-test-basic-project/settings.gradle create mode 100644 integration-tests/gradle/src/main/resources/it-test-basic-project/src/integrationTest/java/org/acme/ExampleResourceIT.java create mode 100644 integration-tests/gradle/src/main/resources/it-test-basic-project/src/main/java/org/acme/ExampleResource.java create mode 100644 integration-tests/gradle/src/main/resources/it-test-basic-project/src/main/resources/application.properties create mode 100644 integration-tests/gradle/src/main/resources/it-test-basic-project/src/test/java/org/acme/ExampleResourceTest.java create mode 100644 integration-tests/gradle/src/main/resources/it-test-basic-project/src/test/resources/application.properties create mode 100644 integration-tests/gradle/src/test/java/io/quarkus/gradle/IntegrationTestBuildTest.java diff --git a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/QuarkusPlugin.java b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/QuarkusPlugin.java index 88a6dd73302f4..d3692901a1e51 100644 --- a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/QuarkusPlugin.java +++ b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/QuarkusPlugin.java @@ -21,6 +21,7 @@ import org.gradle.api.artifacts.ConfigurationContainer; import org.gradle.api.artifacts.ProjectDependency; import org.gradle.api.plugins.BasePlugin; +import org.gradle.api.plugins.JavaBasePlugin; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.tasks.SourceSet; @@ -78,6 +79,7 @@ public class QuarkusPlugin implements Plugin { @Deprecated public static final String BUILD_NATIVE_TASK_NAME = "buildNative"; public static final String TEST_NATIVE_TASK_NAME = "testNative"; + @Deprecated public static final String QUARKUS_TEST_CONFIG_TASK_NAME = "quarkusTestConfig"; @@ -87,6 +89,11 @@ public class QuarkusPlugin implements Plugin { public static final String NATIVE_TEST_IMPLEMENTATION_CONFIGURATION_NAME = "nativeTestImplementation"; public static final String NATIVE_TEST_RUNTIME_ONLY_CONFIGURATION_NAME = "nativeTestRuntimeOnly"; + public static final String INTEGRATION_TEST_TASK_NAME = "quarkusIntTest"; + public static final String INTEGRATION_TEST_SOURCE_SET_NAME = "integrationTest"; + public static final String INTEGRATION_TEST_IMPLEMENTATION_CONFIGURATION_NAME = "integrationTestImplementation"; + public static final String INTEGRATION_TEST_RUNTIME_ONLY_CONFIGURATION_NAME = "integrationTestRuntimeOnly"; + private final ToolingModelBuilderRegistry registry; @Inject @@ -221,7 +228,7 @@ public void execute(Task test) { SourceSetContainer sourceSets = project.getConvention().getPlugin(JavaPluginConvention.class) .getSourceSets(); - SourceSet nativeTestSourceSet = sourceSets.create(NATIVE_TEST_SOURCE_SET_NAME); + SourceSet mainSourceSet = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME); SourceSet testSourceSet = sourceSets.getByName(SourceSet.TEST_SOURCE_SET_NAME); @@ -229,11 +236,11 @@ public void execute(Task test) { quarkusGenerateCodeDev.configure(task -> task.setSourcesDirectories(getSourcesParents(mainSourceSet))); quarkusGenerateCodeTests.configure(task -> task.setSourcesDirectories(getSourcesParents(testSourceSet))); + SourceSet nativeTestSourceSet = sourceSets.create(NATIVE_TEST_SOURCE_SET_NAME); nativeTestSourceSet.setCompileClasspath( nativeTestSourceSet.getCompileClasspath() .plus(mainSourceSet.getOutput()) .plus(testSourceSet.getOutput())); - nativeTestSourceSet.setRuntimeClasspath( nativeTestSourceSet.getRuntimeClasspath() .plus(mainSourceSet.getOutput()) @@ -244,6 +251,24 @@ public void execute(Task test) { testNative.setShouldRunAfter(Collections.singletonList(tasks.findByName(JavaPlugin.TEST_TASK_NAME))); }); + SourceSet intTestSourceSet = sourceSets.create(INTEGRATION_TEST_SOURCE_SET_NAME); + intTestSourceSet.setCompileClasspath( + intTestSourceSet.getCompileClasspath() + .plus(mainSourceSet.getOutput()) + .plus(testSourceSet.getOutput())); + intTestSourceSet.setRuntimeClasspath( + intTestSourceSet.getRuntimeClasspath() + .plus(mainSourceSet.getOutput()) + .plus(testSourceSet.getOutput())); + + tasks.register(INTEGRATION_TEST_TASK_NAME, Test.class, intTestTask -> { + intTestTask.setGroup("verification"); + intTestTask.setDescription("Runs Quarkus integration tests"); + intTestTask.dependsOn(quarkusBuild, tasks.named(JavaBasePlugin.CHECK_TASK_NAME)); + intTestTask.setClasspath(intTestSourceSet.getRuntimeClasspath()); + intTestTask.setTestClassesDirs(intTestSourceSet.getOutput().getClassesDirs()); + }); + tasks.withType(Test.class).forEach(configureTestTask); tasks.withType(Test.class).whenTaskAdded(configureTestTask::accept); @@ -279,6 +304,12 @@ private void createConfigurations(Project project) { configContainer.maybeCreate(NATIVE_TEST_RUNTIME_ONLY_CONFIGURATION_NAME) .extendsFrom(configContainer.findByName(JavaPlugin.TEST_RUNTIME_ONLY_CONFIGURATION_NAME)); + // create a custom configuration to be used for the dependencies of the quarkusIntTest task + configContainer.maybeCreate(INTEGRATION_TEST_IMPLEMENTATION_CONFIGURATION_NAME) + .extendsFrom(configContainer.findByName(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME)); + configContainer.maybeCreate(INTEGRATION_TEST_RUNTIME_ONLY_CONFIGURATION_NAME) + .extendsFrom(configContainer.findByName(JavaPlugin.TEST_RUNTIME_ONLY_CONFIGURATION_NAME)); + ApplicationDeploymentClasspathBuilder.initConfigurations(project); } diff --git a/docs/src/main/asciidoc/gradle-tooling.adoc b/docs/src/main/asciidoc/gradle-tooling.adoc index 8a1155c3cb7f4..4bc737e72fc3d 100644 --- a/docs/src/main/asciidoc/gradle-tooling.adoc +++ b/docs/src/main/asciidoc/gradle-tooling.adoc @@ -501,6 +501,18 @@ quarkus { ==== +== Running integration tests + +Quarkus integration tests (annotated with `@QuarkusIntegrationTest`) will run on the artifact produced by Quarkus. +Those tests can be placed in a `src/integrationTest/java` directory and executed using: + +[source, bash] +---- +./gradlew quarkusIntTest +---- + +This task depends on both `check` and `quarkusBuild` tasks. The final artifact will be produced before running tests. + == Using fast-jar `fast-jar` is now the default quarkus package type. The result of `./gradlew build` command is a new directory under `build` named `quarkus-app`. diff --git a/integration-tests/gradle/src/main/resources/it-test-basic-project/build.gradle b/integration-tests/gradle/src/main/resources/it-test-basic-project/build.gradle new file mode 100644 index 0000000000000..0c0d58d4180b0 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/it-test-basic-project/build.gradle @@ -0,0 +1,36 @@ +plugins { + id 'java' + id 'io.quarkus' +} + +repositories { + // in case a custom local repo is configured we are going to use that instead of the default mavenLocal() + if (System.properties.containsKey('maven.repo.local')) { + maven { + url System.properties.get('maven.repo.local') + } + } else { + mavenLocal() + } + mavenCentral() +} + +dependencies { + implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation 'io.quarkus:quarkus-resteasy' + + testImplementation 'io.quarkus:quarkus-junit5' + testImplementation 'io.rest-assured:rest-assured' +} + +group 'org.acme' +version '1.0.0-SNAPSHOT' + +compileJava { + options.encoding = 'UTF-8' + options.compilerArgs << '-parameters' +} + +compileTestJava { + options.encoding = 'UTF-8' +} diff --git a/integration-tests/gradle/src/main/resources/it-test-basic-project/gradle.properties b/integration-tests/gradle/src/main/resources/it-test-basic-project/gradle.properties new file mode 100644 index 0000000000000..ec2b6ef199c2c --- /dev/null +++ b/integration-tests/gradle/src/main/resources/it-test-basic-project/gradle.properties @@ -0,0 +1,2 @@ +quarkusPlatformArtifactId=quarkus-bom +quarkusPlatformGroupId=io.quarkus diff --git a/integration-tests/gradle/src/main/resources/it-test-basic-project/settings.gradle b/integration-tests/gradle/src/main/resources/it-test-basic-project/settings.gradle new file mode 100644 index 0000000000000..5c456b715cba6 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/it-test-basic-project/settings.gradle @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + // in case a custom local repo is configured we are going to use that instead of the default mavenLocal() + if (System.properties.containsKey('maven.repo.local')) { + maven { + url System.properties.get('maven.repo.local') + } + } else { + mavenLocal() + } + mavenCentral() + gradlePluginPortal() + } + plugins { + id 'io.quarkus' version "${quarkusPluginVersion}" + } +} +rootProject.name='code-with-quarkus' \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/it-test-basic-project/src/integrationTest/java/org/acme/ExampleResourceIT.java b/integration-tests/gradle/src/main/resources/it-test-basic-project/src/integrationTest/java/org/acme/ExampleResourceIT.java new file mode 100644 index 0000000000000..1fc2967a8d5de --- /dev/null +++ b/integration-tests/gradle/src/main/resources/it-test-basic-project/src/integrationTest/java/org/acme/ExampleResourceIT.java @@ -0,0 +1,12 @@ +package org.acme; + +import io.quarkus.test.junit.QuarkusIntegrationTest; +import org.junit.jupiter.api.Test; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.is; + +@QuarkusIntegrationTest +public class ExampleResourceIT extends ExampleResourceTest { + +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/it-test-basic-project/src/main/java/org/acme/ExampleResource.java b/integration-tests/gradle/src/main/resources/it-test-basic-project/src/main/java/org/acme/ExampleResource.java new file mode 100644 index 0000000000000..dfb8c96404500 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/it-test-basic-project/src/main/java/org/acme/ExampleResource.java @@ -0,0 +1,17 @@ +package org.acme; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/hello") +public class ExampleResource { + + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "Hello World"; + } +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/it-test-basic-project/src/main/resources/application.properties b/integration-tests/gradle/src/main/resources/it-test-basic-project/src/main/resources/application.properties new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/integration-tests/gradle/src/main/resources/it-test-basic-project/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/integration-tests/gradle/src/main/resources/it-test-basic-project/src/test/java/org/acme/ExampleResourceTest.java b/integration-tests/gradle/src/main/resources/it-test-basic-project/src/test/java/org/acme/ExampleResourceTest.java new file mode 100644 index 0000000000000..27d0df23c5f78 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/it-test-basic-project/src/test/java/org/acme/ExampleResourceTest.java @@ -0,0 +1,20 @@ +package org.acme; + +import io.quarkus.test.junit.QuarkusTest; +import org.junit.jupiter.api.Test; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.is; + +@QuarkusTest +public class ExampleResourceTest { + + @Test + public void testHelloEndpoint() { + given() + .when().get("/hello") + .then() + .statusCode(200) + .body(is("Hello World")); + } +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/it-test-basic-project/src/test/resources/application.properties b/integration-tests/gradle/src/main/resources/it-test-basic-project/src/test/resources/application.properties new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/IntegrationTestBuildTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/IntegrationTestBuildTest.java new file mode 100644 index 0000000000000..c1745dba95a44 --- /dev/null +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/IntegrationTestBuildTest.java @@ -0,0 +1,22 @@ +package io.quarkus.gradle; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import java.io.File; + +import org.junit.jupiter.api.Test; + +public class IntegrationTestBuildTest extends QuarkusGradleWrapperTestBase { + + @Test + public void shouldRunIntegrationTestAsPartOfBuild() throws Exception { + File projectDir = getProjectDir("it-test-basic-project"); + + BuildResult buildResult = runGradleWrapper(projectDir, "clean", "quarkusIntTest"); + + assertThat(buildResult.getTasks().get(":test")).isEqualTo(BuildResult.SUCCESS_OUTCOME); + assertThat(buildResult.getTasks().get(":check")).isEqualTo(BuildResult.SUCCESS_OUTCOME); + assertThat(buildResult.getTasks().get(":quarkusIntTest")).isEqualTo(BuildResult.SUCCESS_OUTCOME); + } + +} diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/MultiSourceProjectTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/MultiSourceProjectTest.java index 59796e82c7f3e..640b8569b9abb 100644 --- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/MultiSourceProjectTest.java +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/MultiSourceProjectTest.java @@ -14,7 +14,6 @@ public void shouldRunTest() throws Exception { final BuildResult buildResult = runGradleWrapper(projectDir, ":clean", ":test"); assertThat(buildResult.getTasks().get(":test")).isEqualTo(BuildResult.SUCCESS_OUTCOME); - } } diff --git a/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java b/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java index 6f7ce48ec487a..5dfe8ccea9b61 100644 --- a/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java +++ b/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java @@ -498,7 +498,7 @@ private static Path determineBuildOutputDirectory(final URL url) { if (url.getPath().endsWith("test-classes/")) { // we have the maven test classes dir return toPath(url).getParent(); - } else if (url.getPath().endsWith("test/")) { + } else if (url.getPath().endsWith("test/") || url.getPath().endsWith("integrationTest/")) { // we have the gradle test classes dir, build/classes/java/test return toPath(url).getParent().getParent().getParent(); } else if (url.getPath().contains("/target/surefire/")) {