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

Support for additional test-to-main directory mappings #11142

Merged
merged 1 commit into from
Sep 29, 2020

Conversation

roguexz
Copy link
Contributor

@roguexz roguexz commented Aug 1, 2020

It is common practice for Gradle projects to have more than one source set as part of the project setup. For example,

src/
  main/java
  test/java
  funcTest/java
  integTest/java

Currently Quarkus's PathTestHelper does not allow developers to include Quarkus tests in to any of these other locations. This commit proposes a change which will allow supplying the additional source sets to the Quarkus test framework.

Once approved, the subsequent change would be to the Gradle plugin where we can determine the various source sets and supply them as environment variables.

E.g.,
Sample build.gradle snippet.

sourceSets {
    // Functional Tests
    functionalTest {
        java.srcDir file('src/funcTest/java')
        resources.srcDir file('src/funcTest/resources')

        compileClasspath += sourceSets.main.output + configurations.testRuntimeClasspath + configurations.compileOnly
        runtimeClasspath += output + compileClasspath + configurations.jacocoAnt
    }
}

/*
 * Functional tests for this module.
 */
task functionalTest(type: Test, description: 'Functional tests', dependsOn: [processResources, classes]) {
    description = 'Run the functional tests.'
    group = 'verification'
    testClassesDirs = sourceSets.functionalTest.output.classesDirs
    classpath = sourceSets.functionalTest.runtimeClasspath
}

test {
    SourceSet mainSS = project.sourceSets.main
    String mainRelativePath = project.buildDir.relativePath(mainSS.output.classesDirs.singleFile)
    String additionalMappings = project.sourceSets.findAll { ss -> ss != mainSS }
            .collect { SourceSet ss ->
                project.buildDir.relativePath(ss.output.classesDirs.singleFile) + ':' + mainRelativePath
            }.join(',')
    environment 'ADDITIONAL_TEST_TO_MAIN_MAPPINGS', additionalMappings
}

@roguexz
Copy link
Contributor Author

roguexz commented Aug 1, 2020

@aloubyansky

Here is a reproducer: https://github.com/roguexz/quarkus-sample

  • Clone the latest commit
  • Execute ./gradlew clean functionalTest

@geoand
Copy link
Contributor

geoand commented Aug 1, 2020

cc @glefloch

@roguexz
Copy link
Contributor Author

roguexz commented Aug 9, 2020

Gentlemen .. any suggestions regarding this proposal?

@aloubyansky
Copy link
Member

One reason I hesitated to comment last week was that I wanted to check how far we can go with the workspace discovery in Gradle. I suspect we can discover the sources w/o the externally configured environment variable which if we add now we'll have to support later (at least for some time).
I'm still busy looking into other critical issues, so couldn't investigate this further. But if you would like to dig into this @roguexz that could be very useful. Basically, this interface needs to be extended with test sources (and output) dirs https://github.com/quarkusio/quarkus/blob/master/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/resolver/model/WorkspaceModule.java

@glefloch
Copy link
Member

Yes I agree with @aloubyansky, I think we can discover using the Gradle tooling API.

@roguexz
Copy link
Contributor Author

roguexz commented Aug 11, 2020

Let me try this out. I think I had reviewed this code earlier, but let me see what I can do with it. There is always the catch of identifying a sourceSet that should be included as part of the test sources.

@gsmet
Copy link
Member

gsmet commented Sep 18, 2020

@glefloch what's the status of this?

@glefloch
Copy link
Member

As suggested by @aloubyansky we should by able to do that using the quarkus model instead of having to set an environment variable.
@roguexz were you able to give it a try?

@roguexz
Copy link
Contributor Author

roguexz commented Sep 21, 2020

I was tied up with other activities. Just rebased my code. Let me see if I can send a different test sources directory depending on the task being executed.

@roguexz roguexz force-pushed the master branch 2 times, most recently from 87e2d73 to b49c99f Compare September 21, 2020 02:43
@@ -99,6 +100,20 @@
File.separator + "test-classes",
File.separator + "classes");
//endregion

String mappings = System.getenv("ADDITIONAL_TEST_TO_MAIN_MAPPINGS");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@glefloch Based on my analysis, if we want to keep the code impact to a minimum, then I will need to do the following,

  • Identify the test sources and serialize it as part of the plugin (via the tooling API)
  • Read that information in this class and associate the test-to-main mapping so that isInTestDir returns true

If this approach sounds good, then I can serialize it as part of the QuarkusPluginExtension.beforeTest() method.

Apart from the Gradle extension, is there any additional place that needs to be modified?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, actually, we are already scanning workspace here:

private WorkspaceModule getWorkspaceModule(Project project, LaunchMode mode) {

If you can add those source set here, you will be able to get them through the model used :

BuildToolHelper.enableGradleAppModel(projectRoot, "TEST", QuarkusModelHelper.TEST_REQUIRED_TASKS);

@roguexz
Copy link
Contributor Author

roguexz commented Sep 21, 2020

@glefloch - looks like your comment and my code push happened at the same time.

I am looking at the codepaths that you mentioned and am a little lost. PathTestHelper is explicitly mapping test sources to the main sources. I am trying to include an additional test source set.

According to what I understand from the code in QuarkusModelBuilder, we can include additional files (like the test fixtures) to the model (derived from src/main/java). I am not seeing how we can specify test sources through this model, unless we make a change to WorkspaceModule to include something like a testSourceSet and make PathTestHelper to make use of it.

Additionally, with this approach we will end up adding all test source locations upfront, similar to what is being done right now in PathTestHelper. My latest change ensures that we are associating the most likely sourceSet that is appropriate for the current Test task that is being executed.

So, I have the logic .. I need some guidance to identify the correct approach for pushing this mapping to the test helper.

@roguexz
Copy link
Contributor Author

roguexz commented Sep 22, 2020

@glefloch Should we take this conversation to Zulip?

@roguexz
Copy link
Contributor Author

roguexz commented Sep 24, 2020

@aloubyansky

@glefloch & I discussed this issue. Guillaume said that he would look at why PathTestHelper does what it does, but the PR itself is ready for you also to review.

Copy link
Member

@aloubyansky aloubyansky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's ok until we figure out how to properly integrate the workspace model into the junit5 extension. Do you think you could add a test for this issue? Thanks @roguexz

@roguexz
Copy link
Contributor Author

roguexz commented Sep 26, 2020

Incorporating the feedback and updating the PR (with functional-tests)

@@ -27,6 +27,17 @@ repositories {
mavenCentral()
}

sourceSets {
// Functional Tests
funcTest {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am verifying the capability as a functional test.

systemProperty 'org.gradle.testkit.dir', file("${buildDir}/tmp/test-kit")
}

check.dependsOn functionalTest
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build task depends on the check task. So, mvn clean install will in-turn trigger the functional tests

/*
* Functional tests for this module.
*/
task functionalTest(type: Test, description: 'Functional tests', dependsOn: [processResources, classes]) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies for the name confusion. Here is what's happening.

mvn clean install
    --executes--> gradle functionalTest
        --runs-> AdditionalSourceSetsTest
            --executes--> a Gradle build using this build file
                --executes--> this task (which happens to be named as "functionalTest")

@roguexz
Copy link
Contributor Author

roguexz commented Sep 26, 2020

@aloubyansky @glefloch Do let me know if you have a different approach for the tests.

@glefloch
Copy link
Member

@roguexz for this kind of feature, we usually create an integration test in integration-test/gradle module.
In test resources, you can add a sample Gradle project with different test directory and the test will basically run Gradle command on this sample project and assert command result.
Don't hesitate to ping me if you have any problem :)

Copy link
Member

@glefloch glefloch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I commented the PR before starting a review. Your looks good. We used to have issues with test requiring the gradle plugin to be installed.
Can you move it to integration-test/gradle module?

@roguexz
Copy link
Contributor Author

roguexz commented Sep 26, 2020

@glefloch
Relocated the tests to the right module. I have aligned the content to mimic what already exists. Since this is the first time I am contributing to this folder, can you confirm if everything looks fine?

Here are the tests that I ran,

  1. Ensure that the happy path works
./gradlew --no-daemon clean test --tests=AdditionalSourceSetsTest
  1. Update PathTestHelper to ignore the mapping and verify that the test fails with the familiar message test is not part of ...

I am assuming that the CI process should take care of verifying the overall sanity of this PR.

@aloubyansky
Copy link
Member

@roguexz Looks good, thanks! Could you please squash the commits and perhaps review the suggestion from @ebramirez?

@roguexz
Copy link
Contributor Author

roguexz commented Sep 28, 2020

@roguexz Looks good, thanks! Could you please squash the commits and perhaps review the suggestion from @ebramirez?

Sure thing. Will do that shortly

@roguexz
Copy link
Contributor Author

roguexz commented Sep 28, 2020

Done.

  • Incorporated the changes
  • Squashed all commits
  • Did a sanity check on my end.

* Determine test output directory based on the task
* Raise an exception if the mapping data is invalid.
* Include a functional-test for verifying the plugin behavior
@aloubyansky aloubyansky merged commit 3676442 into quarkusio:master Sep 29, 2020
@gsmet gsmet added this to the 1.9.0 - master milestone Oct 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants