Lane
(Cox)
April 6, 2021, 4:42pm
1
Greetings,
I am implementing gradle standalone plugin for testApi (or integration test) which is going to be responsible for the following:
Create testApi sourceSet
Add custom configuration ‘testApiImplementation’
Add some dependencies to ‘testApiImplementation’ configuration.
Add task testApi() for api test execution.
The problem what I met is unavailability to add dependencies to custom configuration, here is the code:
@Override
public void apply(Project project)
{
project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
JavaPluginConvention javaConvention = project.getConvention().getPlugin(JavaPluginConvention.class);
SourceSet main = javaConvention.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);
SourceSet test = javaConvention.getSourceSets().getByName(SourceSet.TEST_SOURCE_SET_NAME);
final Configuration testApiImplementation = project.getConfigurations().create("testApiImplementation")
.setExtendsFrom(Arrays.asList(project.getConfigurations().getByName("testImplementation")));
testApiImplementation.getDependencies().add(project.getDependencies().create("org.testcontainers:testcontainers:1.7.1"));
//project.getDependencies().add(testApiImplementation.getName(), "org.testcontainers:testcontainers:1.7.1");
final SourceSet testApiSourceSet = javaConvention.getSourceSets().create("testApi", sourceSet -> {
sourceSet.setCompileClasspath(project.files(main.getOutput(), test.getOutput()));
sourceSet.setRuntimeClasspath(project.files(main.getOutput(), test.getOutput()));
sourceSet.getJava().srcDir(Arrays.asList("src/testApi/java"));
sourceSet.setRuntimeClasspath(sourceSet.getOutput());
sourceSet.getResources().srcDir("src/testApi/resources");
});
project.getTasks().create("apiTest", Test.class, testApi -> {
testApi.setTestClassesDirs(testApiSourceSet.getOutput().getClassesDirs());
testApi.setClasspath(testApiSourceSet.getRuntimeClasspath());
testApi.useJUnitPlatform();
});
});
}
If I change ‘testApiImplementation’ to just ‘testImplementation’ then desired dependency will appear in
and everything will work properly, but I have no idea how to manage the problem with abcense on dependencies in ‘testApiImplementation’. When I call ‘gradle dependencies’ I see the following:
testImplementation - Implementation only dependencies for source set ‘test’. (n)
— org.junit.jupiter:junit-jupiter-api:5.3.1 (n)
(n) - Not resolved (configuration is not meant to be resolved)
But anyway, dependency doesn’t appear in external libraries section and was not accessible.
Vampire
(Björn Kautler)
April 6, 2021, 5:46pm
2
While I’m not sure why you want to create the configuration manually when creating a sourceSet
already creates the configuration for you, your code is working perfectly fine here.
Are you sure you applied the plugin and also have the java plugin applied?
Lane
(Cox)
April 6, 2021, 6:15pm
3
Neither I sure, so I deleted manual configuration creation and left only code for adding dependencies:
project.getDependencies().add(“testApiImplementation”, “org.testcontainers:testcontainers:1.7.1”);
project.getDependencies().add(“testApiImplementation”, “com.google.guava:guava:30.1.1-jre”);
Yes, I have the following plugin section in build.gradle:
plugins {
id ‘java’
id ‘com.plugin.java-api-test-plugin’ version ‘1.4’
}
By the way, I cannot even add explicitly dependency from build.gradle using dependency section:
Lane
(Cox)
April 6, 2021, 7:46pm
4
Here is plugin project:
java-api-test-plugin.zip (3.3 MB)
And project that uses this plugin:
empty-example.zip (115.3 KB)
Vampire
(Björn Kautler)
April 6, 2021, 10:46pm
5
Ah, “working perfectly fine” meant that dependencies
listed the dependencies fine.
Your problem is, that you setup things not like you intend.
You for example set the compile class path of your new source set to only contain main and test output, but not the actual dependencies you declared.
You would also miss all dependencies of main and test during runtime.
I guess what you want is more something like shown at Gradle User Manual: Version 6.8.3 .
So you probably want something like this:
project.getPlugins().withType(JavaPlugin.class, __ -> {
JavaPluginConvention javaConvention = project.getConvention().getPlugin(JavaPluginConvention.class);
SourceSetContainer sourceSets = javaConvention.getSourceSets();
SourceSet testSourceSet = sourceSets.named(SourceSet.TEST_SOURCE_SET_NAME).get();
SourceSet testApiSourceSet = sourceSets.register("testApi", sourceSet -> {
SourceSet mainSourceSet = sourceSets.named(SourceSet.MAIN_SOURCE_SET_NAME).get();
FileCollection mainAndTestOutput = mainSourceSet.getOutput().plus(testSourceSet.getOutput());
sourceSet.setCompileClasspath(sourceSet.getCompileClasspath().plus(mainAndTestOutput));
sourceSet.setRuntimeClasspath(sourceSet.getRuntimeClasspath().plus(mainAndTestOutput));
}).get();
ConfigurationContainer configurations = project.getConfigurations();
configurations.named(testApiSourceSet.getImplementationConfigurationName()).configure(configuration -> {
configuration.extendsFrom(configurations.named(testSourceSet.getImplementationConfigurationName()).get());
configuration.getDependencies().add(project.getDependencies().create("org.testcontainers:testcontainers:1.7.1"));
});
configurations.named(testApiSourceSet.getRuntimeOnlyConfigurationName()).configure(configuration ->
configuration.extendsFrom(configurations.named(testSourceSet.getRuntimeOnlyConfigurationName()).get()));
project.getTasks().register("apiTest", Test.class, apiTest -> {
apiTest.setDescription("Runs API tests.");
apiTest.setGroup(JavaBasePlugin.VERIFICATION_GROUP);
apiTest.setTestClassesDirs(testApiSourceSet.getOutput().getClassesDirs());
apiTest.setClasspath(testApiSourceSet.getRuntimeClasspath());
apiTest.useJUnitPlatform();
});
});
1 Like
Lane
(Cox)
April 7, 2021, 11:06am
6
It works now. Thanks a lot for you help, I really appreciate it!
1 Like