Skip to content

Commit dc00d60

Browse files
committed
Allow multiple 'whitebox(...) { ... }' calls for one test suite
Resolves #1
1 parent 3eaede4 commit dc00d60

File tree

6 files changed

+232
-31
lines changed

6 files changed

+232
-31
lines changed

build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ java {
1212
}
1313

1414
dependencies {
15+
testImplementation("org.spockframework:spock-core:2.1-groovy-3.0")
1516
testImplementation("org.gradle.exemplar:samples-check:1.0.0")
17+
testRuntimeOnly("org.junit.vintage:junit-vintage-engine")
1618
}
1719

1820
pluginPublishConventions {
@@ -30,5 +32,7 @@ pluginPublishConventions {
3032
}
3133

3234
tasks.test {
35+
useJUnitPlatform()
36+
maxParallelForks = 4
3337
inputs.dir(layout.projectDirectory.dir("samples"))
3438
}

src/main/java/org/gradlex/javamodule/testing/JavaModuleTestingExtension.java

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ public void blackbox(TestSuite jvmTestSuite) {
7272
*/
7373
public void whitebox(TestSuite jvmTestSuite) {
7474
whitebox(jvmTestSuite, NO_OP_ACTION);
75-
7675
}
7776

7877
/**
@@ -114,7 +113,7 @@ private void configureJvmTestSuiteForBlackbox(JvmTestSuite jvmTestSuite) {
114113
tasks.named(sourceSet.getName(), Test.class, t -> {
115114
// Classpath consists only of Jars to include classes+resources in one place
116115
t.setClasspath(configurations.getByName(sourceSet.getRuntimeClasspathConfigurationName()).plus(project.files(jarTask)));
117-
// Rest test classes dir to allow switching back from 'whitebox' to 'blackbox'
116+
// Reset test classes dir
118117
t.setTestClassesDirs(sourceSet.getOutput().getClassesDirs());
119118
});
120119
}
@@ -129,13 +128,19 @@ private void configureJvmTestSuiteForWhitebox(JvmTestSuite jvmTestSuite, Whitebo
129128
tasks.named(testSources.getCompileJavaTaskName(), JavaCompile.class, compileJava -> {
130129
SourceSet sourcesUnderTest = whiteboxJvmTestSuite.getSourcesUnderTest().get();
131130
compileJava.setClasspath(sourcesUnderTest.getOutput().plus(configurations.getByName(testSources.getCompileClasspathConfigurationName())));
132-
compileJava.getOptions().getCompilerArgumentProviders().add(new WhiteboxTestCompileArgumentProvider(
133-
sourcesUnderTest.getJava().getSrcDirs(),
134-
testSources.getJava().getSrcDirs(),
135-
compileJava,
136-
whiteboxJvmTestSuite.getRequires(),
137-
moduleDetector,
138-
moduleInfoParser));
131+
132+
WhiteboxTestCompileArgumentProvider argumentProvider = (WhiteboxTestCompileArgumentProvider) compileJava.getOptions().getCompilerArgumentProviders().stream()
133+
.filter(p -> p instanceof WhiteboxTestCompileArgumentProvider).findFirst().orElseGet(() -> {
134+
WhiteboxTestCompileArgumentProvider newProvider = new WhiteboxTestCompileArgumentProvider(
135+
sourcesUnderTest.getJava().getSrcDirs(),
136+
testSources.getJava().getSrcDirs(),
137+
compileJava,
138+
moduleDetector,
139+
moduleInfoParser);
140+
compileJava.getOptions().getCompilerArgumentProviders().add(newProvider);
141+
return newProvider;
142+
});
143+
argumentProvider.testRequires(whiteboxJvmTestSuite.getRequires().get());
139144
});
140145

141146
tasks.named(testSources.getName(), Test.class, test -> {
@@ -145,15 +150,19 @@ private void configureJvmTestSuiteForWhitebox(JvmTestSuite jvmTestSuite, Whitebo
145150
// Add main classes here so that Gradle finds module-info.class and treats this as a test with module path
146151
test.setTestClassesDirs(sourcesUnderTest.getOutput().getClassesDirs().plus(testSources.getOutput().getClassesDirs()));
147152

148-
test.getJvmArgumentProviders().add(new WhiteboxTestRuntimeArgumentProvider(
149-
sourcesUnderTest.getJava().getSrcDirs(),
150-
testSources.getJava().getClassesDirectory(),
151-
sourcesUnderTest.getOutput().getResourcesDir(),
152-
testSources.getOutput().getResourcesDir(),
153-
whiteboxJvmTestSuite.getRequires(),
154-
whiteboxJvmTestSuite.getOpensTo(),
155-
moduleInfoParser
156-
));
153+
WhiteboxTestRuntimeArgumentProvider argumentProvider = (WhiteboxTestRuntimeArgumentProvider) test.getJvmArgumentProviders().stream()
154+
.filter(p -> p instanceof WhiteboxTestRuntimeArgumentProvider).findFirst().orElseGet(() -> {
155+
WhiteboxTestRuntimeArgumentProvider newProvider = new WhiteboxTestRuntimeArgumentProvider(
156+
sourcesUnderTest.getJava().getSrcDirs(),
157+
testSources.getJava().getClassesDirectory(),
158+
sourcesUnderTest.getOutput().getResourcesDir(),
159+
testSources.getOutput().getResourcesDir(),
160+
moduleInfoParser);
161+
test.getJvmArgumentProviders().add(newProvider);
162+
return newProvider;
163+
});
164+
argumentProvider.testRequires(whiteboxJvmTestSuite.getRequires().get());
165+
argumentProvider.testOpensTo(whiteboxJvmTestSuite.getOpensTo().get());
157166
});
158167

159168
Configuration implementation = configurations.getByName(testSources.getImplementationConfigurationName());

src/main/java/org/gradlex/javamodule/testing/internal/provider/WhiteboxTestCompileArgumentProvider.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@
1616

1717
package org.gradlex.javamodule.testing.internal.provider;
1818

19-
2019
import org.gradlex.javamodule.testing.internal.ModuleInfoParser;
21-
import org.gradle.api.provider.Provider;
2220
import org.gradle.api.tasks.compile.JavaCompile;
2321
import org.gradle.internal.jvm.JavaModuleDetector;
2422
import org.gradle.process.CommandLineArgumentProvider;
@@ -33,19 +31,25 @@ public class WhiteboxTestCompileArgumentProvider implements CommandLineArgumentP
3331
private final Set<File> mainSourceFolders;
3432
private final Set<File> testSourceFolders;
3533
private final JavaCompile task;
36-
private final Provider<List<String>> testRequires;
3734
private final JavaModuleDetector moduleDetector;
3835
private final ModuleInfoParser moduleInfoParser;
3936

40-
public WhiteboxTestCompileArgumentProvider(Set<File> mainSourceFolders, Set<File> testSourceFolders, JavaCompile task, Provider<List<String>> testRequires, JavaModuleDetector moduleDetector, ModuleInfoParser moduleInfoParser) {
37+
private final List<String> allTestRequires = new ArrayList<>();
38+
39+
public WhiteboxTestCompileArgumentProvider(
40+
Set<File> mainSourceFolders, Set<File> testSourceFolders, JavaCompile task,
41+
JavaModuleDetector moduleDetector, ModuleInfoParser moduleInfoParser) {
4142
this.mainSourceFolders = mainSourceFolders;
4243
this.testSourceFolders = testSourceFolders;
4344
this.task = task;
44-
this.testRequires = testRequires;
4545
this.moduleDetector = moduleDetector;
4646
this.moduleInfoParser = moduleInfoParser;
4747
}
4848

49+
public void testRequires(List<String> testRequires) {
50+
allTestRequires.addAll(testRequires);
51+
}
52+
4953
@Override
5054
public Iterable<String> asArguments() {
5155
String moduleName = moduleInfoParser.moduleName(mainSourceFolders);
@@ -58,7 +62,7 @@ public Iterable<String> asArguments() {
5862
args.add("--module-path");
5963
args.add(moduleDetector.inferModulePath(true, task.getClasspath()).getFiles().stream().map(File::getPath).collect(Collectors.joining(cpSeparator)));
6064

61-
for (String testRequires : testRequires.get()) {
65+
for (String testRequires : allTestRequires) {
6266
args.add("--add-modules");
6367
args.add(testRequires);
6468
args.add("--add-reads");

src/main/java/org/gradlex/javamodule/testing/internal/provider/WhiteboxTestRuntimeArgumentProvider.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,30 @@ public class WhiteboxTestRuntimeArgumentProvider implements CommandLineArgumentP
3131
private final Provider<Directory> testClassesFolders;
3232
private final File resourcesUnderTest;
3333
private final File testResources;
34-
private final Provider<List<String>> testRequires;
35-
private final Provider<List<String>> opensTo;
3634
private final ModuleInfoParser moduleInfoParser;
3735

36+
private final List<String> allTestRequires = new ArrayList<>();
37+
private final List<String> allTestOpensTo = new ArrayList<>();
38+
3839
public WhiteboxTestRuntimeArgumentProvider(Set<File> mainSourceFolders,
3940
Provider<Directory> testClassesFolders, File resourcesUnderTest, File testResources,
40-
Provider<List<String>> testRequires, Provider<List<String>> opensTo, ModuleInfoParser moduleInfoParser) {
41+
ModuleInfoParser moduleInfoParser) {
4142

4243
this.mainSourceFolders = mainSourceFolders;
4344
this.testClassesFolders = testClassesFolders;
4445
this.resourcesUnderTest = resourcesUnderTest;
4546
this.testResources = testResources;
46-
this.testRequires = testRequires;
47-
this.opensTo = opensTo;
4847
this.moduleInfoParser = moduleInfoParser;
4948
}
5049

50+
public void testRequires(List<String> testRequires) {
51+
allTestRequires.addAll(testRequires);
52+
}
53+
54+
public void testOpensTo(List<String> testRequires) {
55+
allTestOpensTo.addAll(testRequires);
56+
}
57+
5158
@Override
5259
public Iterable<String> asArguments() {
5360
String moduleName = moduleInfoParser.moduleName(mainSourceFolders);
@@ -62,15 +69,15 @@ public Iterable<String> asArguments() {
6269

6370
List<String> args = new ArrayList<>();
6471

65-
for (String testRequires : testRequires.get()) {
72+
for (String testRequires : allTestRequires) {
6673
args.add("--add-modules");
6774
args.add(testRequires);
6875
args.add("--add-reads");
6976
args.add(moduleName + "=" + testRequires);
7077
}
7178

7279
for (String packageName : allTestClassPackages) {
73-
for (String opensTo : opensTo.get()) {
80+
for (String opensTo : allTestOpensTo) {
7481
args.add("--add-opens");
7582
args.add(moduleName + "/" + packageName + "=" + opensTo);
7683
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package org.gradlex.javamodule.testing.test
2+
3+
import org.gradle.testkit.runner.TaskOutcome
4+
import org.gradlex.javamodule.testing.test.fixture.GradleBuild
5+
import spock.lang.Specification
6+
7+
class CustomizationTest extends Specification {
8+
9+
@Delegate
10+
GradleBuild build = new GradleBuild()
11+
12+
def "can customize whitebox test suites in multiple steps"() {
13+
given:
14+
appBuildFile << '''
15+
javaModuleTesting.whitebox(testing.suites["test"]) {
16+
requires.add("org.junit.jupiter.api")
17+
}
18+
javaModuleTesting.whitebox(testing.suites["test"]) {
19+
opensTo.add("org.junit.platform.commons")
20+
}
21+
'''
22+
appModuleInfoFile << '''
23+
module org.gradlex.test.app {
24+
}
25+
'''
26+
27+
when:
28+
def result = runTests()
29+
30+
then:
31+
result.task(":app:test").outcome == TaskOutcome.SUCCESS
32+
}
33+
34+
def "repetitive blackbox calls on the same test suite have no effect"() {
35+
given:
36+
appBuildFile << '''
37+
javaModuleTesting.blackbox(testing.suites["test"])
38+
javaModuleTesting.blackbox(testing.suites["test"])
39+
'''
40+
appModuleInfoFile << '''
41+
module org.gradlex.test.app {
42+
}
43+
'''
44+
appTestModuleInfoFile << '''
45+
module org.gradlex.test.app.test {
46+
requires org.junit.jupiter.api;
47+
}
48+
'''
49+
50+
when:
51+
def result = runTests()
52+
53+
then:
54+
result.task(":app:test").outcome == TaskOutcome.SUCCESS
55+
}
56+
57+
def "repetitive blackbox calls on the same test suite have no effect"() {
58+
given:
59+
appBuildFile << '''
60+
javaModuleTesting.blackbox(testing.suites["test"])
61+
javaModuleTesting.blackbox(testing.suites["test"])
62+
'''
63+
appModuleInfoFile << '''
64+
module org.gradlex.test.app {
65+
}
66+
'''
67+
appTestModuleInfoFile << '''
68+
module org.gradlex.test.app.test {
69+
requires org.junit.jupiter.api;
70+
}
71+
'''
72+
73+
when:
74+
def result = runTests()
75+
76+
then:
77+
result.task(":app:test").outcome == TaskOutcome.SUCCESS
78+
}
79+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package org.gradlex.javamodule.testing.test.fixture
2+
3+
import org.gradle.testkit.runner.BuildResult
4+
import org.gradle.testkit.runner.GradleRunner
5+
6+
import java.lang.management.ManagementFactory
7+
import java.nio.file.Files
8+
9+
class GradleBuild {
10+
11+
final File projectDir
12+
final File settingsFile
13+
final File appBuildFile
14+
final File appModuleInfoFile
15+
final File appTestModuleInfoFile
16+
17+
final String gradleVersionUnderTest = System.getProperty("gradleVersionUnderTest")
18+
19+
GradleBuild(File projectDir = Files.createTempDirectory("gradle-build").toFile()) {
20+
this.projectDir = projectDir
21+
this.settingsFile = file("settings.gradle.kts")
22+
this.appBuildFile = file("app/build.gradle.kts")
23+
this.appModuleInfoFile = file("app/src/main/java/module-info.java")
24+
this.appTestModuleInfoFile = file("app/src/test/java/module-info.java")
25+
26+
settingsFile << '''
27+
dependencyResolutionManagement { repositories.mavenCentral() }
28+
rootProject.name = "test-project"
29+
include("app")
30+
'''
31+
appBuildFile << '''
32+
plugins {
33+
id("org.gradlex.java-module-dependencies") version "1.0"
34+
id("org.gradlex.java-module-testing")
35+
id("application")
36+
}
37+
dependencies {
38+
testImplementation(platform("org.junit:junit-bom:5.9.0"))
39+
}
40+
application {
41+
mainModule.set("org.gradlex.test.app")
42+
mainClass.set("org.gradlex.test.app.Main")
43+
}
44+
tasks.register("printRuntimeJars") {
45+
doLast { println(configurations.runtimeClasspath.get().files.map { it.name }) }
46+
}
47+
tasks.register("printCompileJars") {
48+
doLast { println(configurations.compileClasspath.get().files.map { it.name }) }
49+
}
50+
'''
51+
52+
file("app/src/test/java/com/example/AppTest.java") << '''
53+
package com.example;
54+
55+
import org.junit.jupiter.api.Test;
56+
57+
public class AppTest {
58+
59+
@Test
60+
void testApp() {
61+
}
62+
}
63+
'''
64+
}
65+
66+
File file(String path) {
67+
new File(projectDir, path).tap {
68+
it.getParentFile().mkdirs()
69+
}
70+
}
71+
72+
BuildResult build() {
73+
runner('build').build()
74+
}
75+
76+
BuildResult run() {
77+
runner('run').build()
78+
}
79+
80+
BuildResult runTests() {
81+
runner(':app:test', '-q').build()
82+
}
83+
84+
BuildResult fail() {
85+
runner('build').buildAndFail()
86+
}
87+
88+
GradleRunner runner(String... args) {
89+
GradleRunner.create()
90+
.forwardOutput()
91+
.withPluginClasspath()
92+
.withProjectDir(projectDir)
93+
.withArguments(Arrays.asList(args) + '-s')
94+
.withDebug(ManagementFactory.getRuntimeMXBean().getInputArguments().toString().contains("-agentlib:jdwp")).with {
95+
gradleVersionUnderTest ? it.withGradleVersion(gradleVersionUnderTest) : it
96+
}
97+
}
98+
}

0 commit comments

Comments
 (0)